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


有什么区别 COPY 和 ADD Dockerfile中的命令,何时使用另一个?


COPY <src> <dest>

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


ADD <src> <dest>

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


1493
2017-07-25 14:31


起源


查看最佳做法: docs.docker.com/engine/userguide/eng-image/... - EricSonaron
截至2018年6月,参考文献称ADD添加到图像(即静态文件),而COPY添加到容器(即图像的运行时实例)。当然这意味着每次图像运行Docker时都会执行COPY,或者这只是一个不一致的术语? - Chris Robinson
我认为这是不一致的术语 - Daniel Stevens


答案:


你应该检查一下 ADD 和 COPY 有关其行为的详尽描述的文档,但简而言之,主要区别在于 ADD 可以做的比 COPY

  • ADD 允许 <src> 成为一个URL
  • 如果 <src> 的参数 ADD 是一个公认的压缩格式的存档,它将被解压缩

请注意 编写Dockerfiles的最佳实践 建议使用 COPY 哪里的魔力 ADD 不需要。否则你(因为你必须查找这个答案)有一天你可能会感到惊讶,当你的意思是复制 keep_this_archive_intact.tar.gz 进入你的容器,但你把内容喷到文件系统上。


1494
2017-07-25 14:52



@patriciasz看起来这个短语最后出现在 v0.9.1。也, github.com/docker-library/golang/issues/18 确认COPY是 不 目前已弃用。 - michielbdejong
......并根据 编写Dockerfiles的最佳实践,COPY不仅仅是 没有弃用,甚至推荐使用ADD(如果可能):“对于不需要ADD的tar自动提取功能的其他项目(文件,目录),你应该总是使用COPY。” - ehdr
@starikovs你总是可以使用linter而不是阅读最佳实践(github.com/RedCoolBeans/dockerlint)= - )如果没有遵循这种做法,那个linter会发出警告。 - Spain Train
它可能不会被弃用,因为ADD的自动提取行为不一致,具体取决于您是否使用了URL。 - xenoterracide
docs.docker.com/engine/userguide/eng-image/... - dimpiax


COPY 是

与“ADD”相同,但没有tar和远程URL处理。

参考 直接来自源代码


296
2017-09-30 16:13





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

因为图像尺寸很重要,使用 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


116
2017-10-02 08:21



也可以看看 这个提交从八月开始 哪里 Docker的Dockerfile本身从ADD切换到COPY - michielbdejong
Docker说更喜欢 COPY,因为它更透明。来自 Docker文件最佳实践 (情节中字): Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features that are not immediately obvious. - schemar


来自Docker文档:

添加或复制

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

更多: 编写Dockerfiles的最佳实践


95
2017-08-10 15:19





如果要将xx.tar.gz添加到a /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仅使用一层。


27
2018-04-25 07:07



任何理由不仅仅是两层? RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz - Stephen C


来自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/

与放置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。“


11
2018-06-12 05:29





重要的提示

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

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


0
2018-06-07 08:00



对于最新版本的Docker,这仍然适用吗? - Navin


COPY 将文件/目录从主机复制到您的映像。

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

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

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


0
2018-05-31 12:11





docker build -t {image name} -v {host directory}:{temp build directory} .

这是将文件复制到图像的另一种方法。 -v选项临时创建我们在构建过程中使用的卷。

这与其他卷不同,因为它仅为构建安装主机目录。可以使用标准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

-1
2017-09-23 19:32



您看到该选项的是哪个docker版本? 它没有记录 并且不适用于我的1.12.1客户端。 - BMitch
实际上,这个功能还没有被包含在主要版本中,并且仍然有很多关于这个主题的讨论,所以我们不应该在很长一段时间内看到它...查看错误报告了解更多信息: github.com/docker/docker/issues/14080。 - jwatkins
是的,没有这样的选择(在最新版本17.06中检查)。这个答案有误导性。 unknown shorthand flag: 'v' in -v - Kirby
确实有误导性的评论 - Guido van Steen