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

COPY <src> <dest>

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

ADD <src> <dest>

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


当前回答

创建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

其他回答

资料来源: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,因为它更显式。

COPY不支持URL方案的<src>。COPY不会解压缩压缩文件。对于指令<src><dest>,如果<src>是tar压缩文件,且<dest>不以斜杠结尾:ADD将<dest>视为一个目录,并将<src>解压缩到该目录。COPY将<dest>视为一个文件,并将<src>写入其中。COPY支持通过--from arg覆盖生成上下文。

创建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

副本为

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

直接从源代码引用。

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