COPY
和 ADD
命令在 Dockerfile 中有什么区别?我应该何时使用其中一个而不是另一个?
COPY <src> <dest>
COPY指令会将
<src>
中的新文件复制到容器文件系统的路径<dest>
ADD <src> <dest>
ADD 指令将从
<src>
复制新文件,并将其添加到容器的文件系统中的路径<dest>
。
COPY
和 ADD
命令在 Dockerfile 中有什么区别?我应该何时使用其中一个而不是另一个?
COPY <src> <dest>
COPY指令会将
<src>
中的新文件复制到容器文件系统的路径<dest>
ADD <src> <dest>
ADD 指令将从
<src>
复制新文件,并将其添加到容器的文件系统中的路径<dest>
。
ADD
和COPY
的文档,以获取更详细的行为描述,但简而言之,主要区别在于ADD
比COPY
功能更强大:
ADD
允许<src>
是一个URLADD
的文档中指出:请注意,编写Dockerfile的最佳实践建议在不需要如果
<src>
是一个本地tar归档文件,且是已知的压缩格式(identity,gzip,bzip2或xz),则它将被解压为一个目录。来自远程URL的资源不会被解压缩。
ADD
的神奇功能时使用COPY
。否则,你(因为你不得不查找这个答案)可能会在某一天感到惊讶,当你想要将keep_this_archive_intact.tar.gz
复制到你的容器中时,却意外地将其内容喷洒到你的文件系统上。这一点有官方文档说明: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 自动解压能力的其他项目(文件、目录),您应始终使用 COPY。来自Docker文档:
ADD或COPY
虽然ADD和COPY在功能上类似,但一般而言,COPY更受欢迎。这是因为它比ADD更透明。COPY仅支持将本地文件基本复制到容器中,而ADD具有一些特性(例如仅限本地的tar文件提取和远程URL支持),这些特性不是立即明显的。因此,ADD最好用于将本地tar文件自动提取到镜像中,例如ADD rootfs.tar.xz /。
更多信息:编写Dockerfile的最佳实践
/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只使用一个层级。
ADD
和 COPY
。虽然它们的功能范围略有不同,但本质上执行相同的任务。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
===
由于某些功能问题,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。通过这样做,您可以避免创建额外的镜像层并节省空间。
COPY
命令可将文件/目录从主机复制到镜像。
ADD
命令不仅可以从主机复制文件/目录到镜像,还可以获取远程URL、提取TAR文件等等...
使用COPY
仅将文件和/或目录简单地复制到构建环境中。
使用ADD
下载远程资源,提取TAR文件等等...
根据Docker文档:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy
"尽管ADD和COPY在功能上类似,但通常情况下,推荐使用COPY。因为它比ADD更加透明。COPY仅支持将本地文件简单复制到容器中,而ADD具有一些特性(例如仅本地tar文件提取和远程URL支持),这些特性不够明显。因此,ADD最佳用法是将本地tar文件自动解压缩到镜像中,例如:ADD rootfs.tar.xz /。
如果你的多个Dockerfile步骤需要从上下文中使用不同的文件,请逐个COPY它们,而不是一次性复制所有文件。这将确保每个步骤的构建缓存仅在特定所需文件更改时被失效(强制重新运行该步骤)。
例如:
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
RUN步骤中,如果您将COPY . /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。
来源: https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile:
COPY和ADD都是Dockerfile指令,具有类似的用途。它们允许您将文件从特定位置复制到Docker镜像中。
COPY使用src和destination参数。它只允许您将本地文件或目录(即构建Docker镜像的主机)复制到Docker镜像本身中。
ADD也可以做到这一点,但它还支持另外两种来源。首先,您可以使用URL而不是本地文件/目录。其次,您可以直接将源中的tar文件提取到目标位置。
使用ADD的一个有效用例是,当您想要将本地tar文件提取到Docker镜像中的特定目录时。
如果要将本地文件复制到Docker镜像中,请始终使用COPY,因为它更明确。
docker cp
(Docker 命令行)将复制文件到/从正在运行的容器。Dockerfile 中的 COPY 指令用于构建镜像。 - Jurn Ho