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

Dockerfile 中的COPYADD命令之间有什么区别,何时可以在另一个上使用?

COPY <src> <dest>

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

ADD <src> <dest>

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

答案

您应该查看ADDCOPY文档以详尽描述它们的行为,但简而言之,主要区别在于ADD可以做的比COPY还多:

  • ADD允许<src>作为 URL
  • 关于下面的评论, ADD 文档明确指出:

    如果是以公认的压缩格式(身份,gzip,bzip2 或 xz)作为本地 tar 归档文件,则将其解压缩为目录。来自远程 URL 的资源不会被解压缩。

请注意, 编写 Dockerfile最佳实践建议在不需要ADD情况下使用COPY 。否则,当您打算将keep_this_archive_intact.tar.gz复制到您的容器中时,您(因为您必须查找此答案)很可能会感到惊讶,而是将内容喷洒到文件系统上。

COPY

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

直接从源代码中引用。

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

由于图像大小很重要,因此强烈建议不要使用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

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

从 Docker 文档中:

添加或复制

尽管 ADD 和 COPY 在功能上相似,但通常来说 COPY 是首选。那是因为它比 ADD 更透明。 COPY 仅支持将本地文件基本复制到容器中,而 ADD 的某些功能(如仅本地 tar 提取和远程 URL 支持)并不是立即显而易见的。因此,ADD 的最佳用途是将本地 tar 文件自动提取到映像中,就像在 ADD rootfs.tar.xz / 中一样。

更多: 编写 Dockerfile 的最佳实践

如果要将 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 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 在功能上相似,但通常来说,首选 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。”

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

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

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

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

来源: 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,因为它更加明确。

重要的提示

我必须在 Docker 映像中COPY并解压缩 Java 包。当我比较使用 ADD 创建的 docker 映像大小时,它比使用 COPY,tar -xzf * .tar.gz 和 rm * .tar.gz 创建的映像大 180MB。

这意味着尽管 ADD 删除了 tar 文件,但仍保留在某个位置。并使其图像更大!

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

文档中

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