Dockerfile中的`COPY`和`ADD`命令有什么区别?
Dockerfile中的COPY
和ADD
命令之间有什么区别,以及什么时候使用另一个呢?
COPY <src> <dest>
COPY指令将从
<src>
复制新文件,并将它们添加到path<dest>
的容器文件系统中
ADD <src> <dest>
ADD指令将从
<src>
复制新文件,并将它们添加到path<dest>
的容器文件系统中。
您应该检查ADD
和COPY
文档以详细描述它们的行为,但简而言之,主要区别在于ADD
可以做的不仅仅是COPY
:
-
ADD
允许<src>
成为一个URL - 如果
ADD
的<src>
参数是以可识别的压缩格式存档,则它将被解压缩
请注意, 编写Dockerfiles的最佳实践build议使用COPY
,其中不需要ADD
的魔力。 否则,当你将keep_this_archive_intact.tar.gz
复制到你的容器中时,你(因为你不得不查找这个答案)可能会感到惊讶,而是将内容喷到你的文件系统上。
COPY
是
与“ADD”相同,但没有tar和远程URL处理。
直接从源代码中引用。
关于这一点有一些官方文档: 写入Dockerfiles的最佳实践
由于图像大小很重要,强烈build议使用
ADD
从远程URL获取软件包; 你应该使用curl
或wget
来代替。 这样,你可以删除不再需要的文件,而不需要在图像中添加另一个图层。
RUN mkdir -p /usr/src/things \ && curl -SL http://example.com/big.tar.gz \ | tar -xJC /usr/src/things \ && make -C /usr/src/things all
对于不需要
ADD
的tar自动提取function的其他项目(文件,目录),您应该始终使用COPY
。
从Docker文档:
ADD或COPY
尽pipeADD和COPY在function上是相似的,但一般来说,COPY是首选。 这是因为它比ADD更透明。 COPY只支持将本地文件复制到容器中,而ADD则具有一些特性(如仅限本地的tar提取和远程URL支持),这些function并不是很明显。 因此,ADD的最佳用法是将本地tar文件自动提取到映像中,如ADD rootfs.tar.xz /中所示。
更多: 编写Dockerfiles的最佳实践
如果要将xx.tar.gz添加到容器中的/usr/local
,请将其解压缩,然后删除无用的压缩包。
对于COPY:
COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/ RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local RUN rm /tmp/jdk-7u79-linux-x64.tar.gz
对于ADD:
ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/
ADD支持仅本地tar提取。 除此之外,COPY将使用三层,但ADD仅使用一层。
从Docker文档: https : //docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy
“虽然ADD和COPY在function上是相似的,但一般来说,COPY是首选,这是因为它比ADD更透明,COPY只支持将本地文件复制到容器中,而ADD具有一些function(如仅限本地的tar提取和远程URL支持),因此,ADD的最佳用途是将本地tar文件自动提取到映像中,如ADD rootfs.tar.xz /中所示。
如果您有多个使用您的上下文中的不同文件的Dockerfile步骤,请单独复制它们,而不是一次全部复制。 这将确保每个步骤的构buildcaching仅在特定需要的文件发生更改时才会失效(强制重新运行该步骤)。
例如:
COPY requirements.txt /tmp/ RUN pip install --requirement /tmp/requirements.txt COPY . /tmp/
导致RUN步骤中caching失效的次数比放置COPY的次数less。 / tmp /之前。
由于图像大小很重要,强烈build议使用ADD从远程URL获取软件包; 你应该使用curl或wget来代替。 这样,你可以删除不再需要的文件,而不需要在图像中添加另一个图层。 例如,你应该避免做这样的事情:
ADD http://example.com/big.tar.xz /usr/src/things/ RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things RUN make -C /usr/src/things all
而是,做一些事情:
RUN mkdir -p /usr/src/things \ && curl -SL htt,p://example.com/big.tar.xz \ | tar -xJC /usr/src/things \ && make -C /usr/src/things all
对于不需要ADD的tar自动提取function的其他项目(文件,目录),您应该始终使用COPY。
COPY
将适用于大多数情况。
ADD
具有COPY
所有function,并具有以下附加function:
允许在图像中的tar文件自动提取 ,例如,
ADD app.tar.gz /opt/var/myapp.
允许从远程URL下载文件。 但是,下载的文件将成为图像的一部分。 这会导致图像大小膨胀。 因此, build议使用cURL或Wget来明确下载存档,提取和删除存档。
docker build -t {image name} -v {host directory}:{temp build directory} .
这是将文件复制到图像的另一种方法。 -v选项临时创build一个在构build过程中使用的卷。
这与其他卷不同,因为它仅为构build安装主机目录。 文件可以使用标准的cp命令复制。
另外,像curl和wget一样,它可以在一个命令堆栈中运行(运行在一个容器中),而不会增加图像的大小。 ADD和COPY是不可堆叠的,因为它们在独立的容器中运行,而对那些在附加容器中执行的文件的后续命令将会乘以图像大小:
通过如此设置的选项:
-v /opt/mysql-staging:/tvol
以下将在一个容器中执行:
RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \ mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \ mkdir /u1/mysql/mysql-files && \ mkdir /u1/mysql/innodb && \ mkdir /u1/mysql/innodb/libdata && \ mkdir /u1/mysql/innodb/innologs && \ mkdir /u1/mysql/tmp && \ chmod 750 /u1/mysql/mysql-files && \ chown -R mysql /u1/mysql && \ chgrp -R mysql /u1/mysql
重要的提示
我不得不在我的docker镜像中复制和解压Java包。 当我比较使用ADD创build的docker图像大小时,它比使用COPY创build的大180MB,tar -xzf * .tar.gz和rm * .tar.gz
这意味着虽然ADD删除了tar文件,但它仍然保留在某个地方。 它使图像大!