Dockerfile中的`COPY`和`ADD`命令有什么区别?

Ste*_*eve 1991 docker dockerfile

是什么之间的差异COPY,并ADD在Dockerfile命令,当我将使用一个比其他?

COPY <src> <dest>
Run Code Online (Sandbox Code Playgroud)

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

ADD <src> <dest>
Run Code Online (Sandbox Code Playgroud)

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

ice*_*ime 1992

您应该查看ADDCOPY记录其行为的详尽描述,但简而言之,主要区别在于它ADD可以做的不仅仅是COPY:

  • ADD允许<src>成为一个URL
  • 如果ADD参数COPY是具有已识别压缩格式的存档,则将对其进行解压缩

请注意,编写Dockerfiles最佳实践建议使用ADD不需要魔法的地方keep_this_archive_intact.tar.gz.否则你(因为你必须查找这个答案)有可能会在你想要复制ADD到容器中时感到惊讶,而是将内容喷到你的文件系统上.

  • 只想澄清一些事情:使用带有URL的ADD到.tar.gz不要将存档提取到文件系统(我现在仔细检查以确定它已经确认) (47认同)
  • 这是必不可少的信息,官方Dockerfile参考没有通过这种方式澄清差异是一种犯罪. (26认同)
  • COPY 允许 --from=&lt;name|index&gt;,但我找不到对 ADD 的相同支持 (6认同)
  • @SantoshKumarArjunan:Docker文档陈述了有关ADD和自动tar提取的以下内容:`如果&lt;src&gt;是采用公认压缩格式(身份,gzip,bzip2或xz)的本地tar存档,则将其解压缩为目录。不会解压缩来自远程URL的资源。`[Docker ADD](https://docs.docker.com/engine/reference/builder/#add) (3认同)

cai*_*ike 426

COPY

与"ADD"相同,但没有tar和远程URL处理.

直接从源代码引用.

  • 我是否正确看到了这一点:`ADD`也**创建了不存在的目录**.所以,尽管在整个帖子中有点气馁,但它比'COPY'有**优势**因为你不必运行`mkdir`并节省一些打字 (9认同)
  • 这是我读过的最好的答案 (6认同)
  • 多么明显!毕竟,源代码是文档。&lt;/ snark&gt; (5认同)
  • 感谢简短而可信的答案,并为实际源代码的链接+1! (4认同)

Vic*_*kin 135

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

由于图像大小很重要,ADD因此强烈建议不要使用从远程URL获取包.你应该使用curlwget代替.这样,您可以删除提取后不再需要的文件,并且不必在图像中添加其他图层.

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
Run Code Online (Sandbox Code Playgroud)

对于不需要ADDtar自动提取功能的其他项目(文件,目录),您应该始终使用COPY.

  • Docker说更喜欢`COPY`,因为它更透明.来自[Docker文件最佳实践](https://docs.docker.com/articles/dockerfile_best-practices/#add-or-copy)(2014-12-15):`虽然ADD和COPY在功能上相似,但一般来说说,COPY是首选.那是因为它比ADD更透明.COPY仅支持将本地文件基本复制到容器中,而ADD具有一些不是很明显的功能 (16认同)
  • 另请参见[8月份提交](https://github.com/wking/dockerfile/commit/707be173773a520571056001fec2a27da2e72235),其中[Docker文件为Docker本身从ADD切换到COPY](https://github.com/docker/docker /斑点/主/ Dockerfile#L113) (2认同)

edd*_*ddd 113

来自Docker文档:

添加或复制

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

更多:编写Dockerfiles的最佳实践


小智 39

如果要将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
Run Code Online (Sandbox Code Playgroud)

对于ADD:

ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/
Run Code Online (Sandbox Code Playgroud)

ADD支持仅本地tar提取.除此之外,COPY将使用三层,但ADD仅使用一层.

  • 任何理由不仅仅是两层?`RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C/usr/local && rm/tmp/jdk-7u79-linux-x64.tar.gz` (2认同)

Yog*_*cha 29

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

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

泊坞窗ADD命令

让我们首先注意到该ADD命令比COPY. 自 Docker 平台推出以来,该ADD指令已成为其命令列表的一部分。

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

ADD命令的基本语法是:

ADD <src> … <dest>
Run Code Online (Sandbox Code Playgroud)

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

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

ADD /source/file/path  /destination/path
Run Code Online (Sandbox Code Playgroud)

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

ADD http://source.file/url  /destination/path
Run Code Online (Sandbox Code Playgroud)

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

ADD source.file.tar.gz /temp
Run Code Online (Sandbox Code Playgroud)

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

泊坞窗COPY命令

由于一些功能问题,Docker 不得不引入一个额外的命令来复制内容—— COPY.

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

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

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

输入来源以及您希望命令提取内容的位置,如下所示:

COPY <src> … <dest> 
Run Code Online (Sandbox Code Playgroud)

例如:

COPY /source/file/path  /destination/path 
Run Code Online (Sandbox Code Playgroud)

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

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

Docker 的官方文档指出COPY应该始终是首选指令,因为它比ADD.

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

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

  • 您已从 https://phoenixnap.com/kb/docker-add-vs-copy 复制了整个答案。不要将他人的作品当作自己的作品。 (5认同)

jhp*_*hpg 14

来自Docker文档:https: //docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

"尽管ADD和COPY在功能上相似,但一般来说,COPY是首选.这是因为它比ADD更透明.COPY仅支持将本地文件基本复制到容器中,而ADD具有一些功能(如仅限本地的tar提取和因此,ADD的最佳用途是将本地tar文件自动提取到图像中,如ADD rootfs.tar.xz /中所示.

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

例如:

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/
Run Code Online (Sandbox Code Playgroud)

与放置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 Code Online (Sandbox Code Playgroud)

而是做一些像:

 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
Run Code Online (Sandbox Code Playgroud)

对于不需要ADD的tar自动提取功能的其他项目(文件,目录),您应该始终使用COPY."


JSO*_*C11 10

COPY 将文件/目录从主机复制到图像。

ADD 将文件/目录从主机复制到图像,但也可以获取远程URL,提取TAR文件等。

使用COPY简单复制文件和/或目录到构建上下文。

使用ADD下载远程资源,提取TAR文件等。


Dre*_*oon 10

  1. COPY不支持<src>URL 方案。
  2. COPY不解压压缩文件。
    对于instruction <src> <dest>, if<src>是一个 tar 压缩文件并且<dest>不以尾部斜杠结尾:
    ADD将其视为<dest>一个目录并解压<src>到其中。
    COPY将其视为<dest>一个文件并写入<src>它。
  3. COPY支持通过 arg 覆盖构建上下文--from


小智 7

由于 Docker 17.05COPY多阶段构建中--from标志一起使用,以将工件从先前构建阶段复制到当前构建阶段。

文档

COPY 可以选择接受一个标志--from=<name|index>,该标志可用于将源位置设置为先前的构建阶段(使用 FROM .. AS 创建),该阶段将用于代替用户发送的构建上下文。


VKa*_*atz 6

ADD指令从本地或远程源复制文件或文件夹并将它们添加到容器的文件系统中。它用于复制本地文件,这些文件必须位于工作目录中。ADD指令将本地.tar文件解压到目标图像目录。

例子

ADD http://someserver.com/filename.pdf /var/www/html
Run Code Online (Sandbox Code Playgroud)

COPY从工作目录复制文件并将它们添加到容器的文件系统中。无法使用URL此 Dockerfile 指令来复制远程文件。

例子

COPY Gemfile Gemfile.lock ./
COPY ./src/ /var/www/html/
Run Code Online (Sandbox Code Playgroud)


小智 5

重要的提示

我不得不COPY在我的 docker 镜像中解压 java 包。当我比较使用 ADD 创建的 docker 镜像大小时,它比使用 COPY、tar -xzf *.tar.gz 和 rm *.tar.gz 创建的镜像大 180MB

这意味着虽然 ADD 删除了 tar 文件,但它仍然保留在某处。它使图像更大!!


Sha*_*thi 5

来源:https : //nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile

COPY和ADD都是具有相似用途的Dockerfile指令。它们使您可以将文件从特定位置复制到Docker映像中。

COPY接收src和目的地。它仅允许您从主机(构建Docker映像的机器)的本地文件或目录中复制到Docker映像本身。

ADD也允许您执行此操作,但是它还支持其他2个来源。首先,您可以使用URL代替本地文件/目录。其次,您可以将tar文件从源直接提取到目标中

当您想将本地tar文件提取到Docker映像中的特定目录中时,ADD的有效用例。

如果要将本地文件复制到Docker映像,请始终使用COPY,因为它更加明确。


bin*_* li 5

如果您有 foo.tar.gz 文件,请比较以下命令。ADD命令创建的层数比COPY命令少,并且在推送docker镜像时节省了大量的网络流量。

ADD foo.tar.gz /
Run Code Online (Sandbox Code Playgroud)
COPY foo.tar.gz /
RUN tar -zxvf foo.tar.gz
RUN rm -rf foo.tar.gz
Run Code Online (Sandbox Code Playgroud)