Dockerfile中的COPY
和ADD
命令之间有什么区别,何时可以在另一个之上使用?
COPY <src> <dest>
COPY指令将从以下位置复制新文件
<src>
并将其添加到容器的文件系统中:<dest>
ADD <src> <dest>
ADD指令将从复制新文件
<src>
并将其添加到位于path的容器的文件系统中<dest>
。
COPY
每次运行时都执行,因为它不一定有权访问原始上下文来获取内容。
Dockerfile中的COPY
和ADD
命令之间有什么区别,何时可以在另一个之上使用?
COPY <src> <dest>
COPY指令将从以下位置复制新文件
<src>
并将其添加到容器的文件系统中:<dest>
ADD <src> <dest>
ADD指令将从复制新文件
<src>
并将其添加到位于path的容器的文件系统中<dest>
。
COPY
每次运行时都执行,因为它不一定有权访问原始上下文来获取内容。
Answers:
您应该查看ADD
和COPY
文档以获取有关其行为的更详细描述,但简而言之,主要区别在于ADD
可以做的还不止COPY
:
ADD
允许<src>
成为网址ADD
文档指出:
如果是以公认的压缩格式(身份,gzip,bzip2或xz)的本地tar归档文件,则将其解压缩为目录。来自远程URL的资源不会被解压缩。
请注意,编写Dockerfile的最佳实践建议COPY
在ADD
不需要魔术的地方使用。否则,当您打算复制到容器中时,您(由于必须查找此答案)可能有一天会感到惊讶keep_this_archive_intact.tar.gz
,而是将内容喷洒到文件系统上。
If <src> is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed.
Docker ADD
关于这一点,有一些官方文档:编写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
tar自动提取功能的其他项目(文件,目录),应始终使用COPY
。
COPY
,因为它更加透明。从Docker File Best Practices(2014-12-15): 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.
从Docker文档中:
添加或复制
尽管ADD和COPY在功能上相似,但通常来说COPY是首选。那是因为它比ADD更透明。COPY仅支持将本地文件基本复制到容器中,而ADD的某些功能(如仅本地tar提取和远程URL支持)并不立即显而易见。因此,与ADD rootfs.tar.xz /中一样,ADD的最佳用途是将本地tar文件自动提取到映像中。
如果要将xx.tar.gz添加到/usr/local
in容器中,请解压缩它,然后删除无用的压缩包。
对于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仅使用一层。
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz
来自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。”
来源: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,因为它更加明确。
创建Dockerfile时,有两个命令可用于将文件/目录复制到其中: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
请记住,您无法从URL下载和解压缩文件/目录。将外部软件包复制到本地文件系统时,该命令不会解压缩它们。
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更安全,更有效。这样可以避免创建额外的图像层并节省空间。
我不得不COPY
在我的docker映像中解压缩java包。当我比较使用ADD创建的docker映像大小时,它比使用COPY,tar -xzf * .tar.gz和rm * .tar.gz创建的映像大180MB。
这意味着尽管ADD删除了tar文件,但仍保留在某个位置。并使其图像更大!
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
unknown shorthand flag: 'v' in -v