Dockerfile中的COPY和ADD命令有什么区别?我什么时候可以使用其中一个命令而不是另一个命令?

COPY <src> <dest>

COPY指令将从<src>复制新文件,并将它们添加到路径<dest>的容器文件系统中

ADD <src> <dest>

ADD指令将从<src>复制新文件,并将它们添加到路径<dest>的容器文件系统中。


当前回答

从Docker文档:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-或复制

“虽然ADD和COPY在功能上相似,但一般来说,COPY是首选。这是因为它比ADD更透明。COPY仅支持将本地文件复制到容器中的基本功能,而ADD具有一些功能(如仅本地tar提取和远程URL支持)这不是立即显而易见的。因此,ADD的最佳用途是将本地tar文件自动提取到图像中,如ADD rootfs.tar.xz/中所示。

如果您有多个Dockerfile步骤使用上下文中不同的文件,请单独复制它们,而不是一次复制所有文件。这将确保只有在特定需要的文件发生更改时,每个步骤的构建缓存才会失效(强制重新运行该步骤)。

例如:

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/

与放置COPY相比,RUN步骤的缓存无效次数更少/tmp/之前。

因为图像大小很重要,所以强烈不建议使用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自动提取功能的其他项目(文件、目录),您应该始终使用COPY。"

其他回答

假设您有一个tar文件,您想在将其放入容器后解压缩它,然后删除它,您可以使用COPY命令执行此操作。但各种命令可能是1)将tar文件复制到目标,2)。解压缩,3)删除tar文件。如果您分三步完成此操作,则在每一步之后都会创建一个新图像。您可以使用&一步到位,但这很麻烦。

但是你使用了ADD,那么Docker会为你处理所有的事情,只会创建一个中间映像。

ADD和COPY都具有将文件和目录从源复制到目标的相同功能,但ADD具有额外的文件提取和URL文件提取功能。最佳做法是仅在复制操作中使用COPY,避免在许多领域使用ADD。该链接将通过一些简单的示例解释dockerfile中COPY和ADD之间的区别

创建Dockerfile时,可以使用两个命令将文件/目录复制到其中:ADD和copy。尽管它们的功能范围略有不同,但本质上执行相同的任务。

那么,为什么我们有两个命令,我们如何知道何时使用其中一个或另一个?

DOCKER ADD命令

===

让我们首先注意ADD命令比COPY命令旧。自Docker平台推出以来,ADD指令一直是其命令列表的一部分。

该命令将文件/目录复制到指定容器的文件系统。

ADD命令的基本语法是:

ADD <src> … <dest>

它包括要复制的源(<src>)和要存储它的目标(<dest>)。如果源是一个目录,ADD会复制其中的所有内容(包括文件系统元数据)。

例如,如果文件在本地可用,并且您希望将其添加到图像目录中,请键入:

ADD /source/file/path  /destination/path

ADD还可以从URL复制文件。它可以下载外部文件并将其复制到所需的目标。例如:

ADD http://source.file/url  /destination/path

另一个特性是它复制压缩文件,自动将内容提取到给定的目标。此功能仅适用于本地存储的压缩文件/目录。

ADD source.file.tar.gz /temp

请记住,您不能从URL下载和提取压缩文件/目录。当将外部包复制到本地文件系统时,该命令不会解压缩外部包。

DOCKER COPY命令

===

由于一些功能问题,Docker不得不引入一个复制内容的附加命令——COPY。

与紧密相关的ADD命令不同,COPY只有一个指定的功能。它的作用是以现有格式在指定位置复制文件/目录。这意味着它不处理提取压缩文件,而是按原样复制。

该指令只能用于本地存储的文件。因此,不能将其与URL一起用于将外部文件复制到容器中。

要使用COPY指令,请遵循基本命令格式:

键入源以及命令提取内容的位置,如下所示:

COPY <src> … <dest> 

例如:

COPY /source/file/path  /destination/path 

要使用哪个命令?(最佳实践)

考虑到引入COPY命令的情况,很明显,保留ADD是一个必要的问题。Docker发布了一份官方文档,概述了编写Dockerfile的最佳实践,其中明确建议不要使用ADD命令。

Docker的官方文档指出,COPY应该始终是一条指令,因为它比ADD更透明。

如果需要从本地构建上下文复制到容器中,请坚持使用copy。

Docker团队也强烈反对使用ADD从URL下载和复制包。相反,在RUN命令中使用wget或curl更安全、更有效。这样做可以避免创建额外的图像层并节省空间。

裁判:https://phoenixnap.com/kb/docker-add-vs-copy

从Docker文档:

添加或复制虽然ADD和COPY功能相似,但一般来说,COPY是首选。这是因为它比ADD更透明。COPY仅支持将本地文件基本复制到容器中,而ADD具有一些不明显的功能(如仅本地的tar提取和远程URL支持)。因此,ADD的最佳用途是将本地tar文件自动提取到图像中,如ADD rootfs.tar.xz/中所示。

更多:编写Dockerfile的最佳实践

关于这一点,有一些官方文档:编写Dockerfile的最佳实践

因为图像大小很重要,所以强烈不建议使用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自动提取功能的其他项目(文件、目录),您应该始终使用COPY。