Dockerfile中COPY和ADD命令的区别
技术背景
在创建Dockerfile时,有两个命令可用于将文件或目录复制到容器中,即ADD
和COPY
。虽然它们在功能范围上有细微差异,但本质上执行的是相同的任务。ADD
命令是Docker平台推出以来就存在的,而COPY
命令是由于ADD
的一些功能问题后续引入的。
实现步骤
ADD命令
ADD
命令的基本语法为:
它将文件或目录复制到指定容器的文件系统中。其中<src>
是要复制的源,<dest>
是存储的目标位置。
- 若源是本地文件或目录,
ADD
会复制其中的所有内容(包括文件系统元数据)。例如:
1
| ADD /source/file/path /destination/path
|
1
| ADD http://source.file/url /destination/path
|
- 对于本地存储的压缩文件(如
.tar.gz
、.tar.xz
等),ADD
会自动将其内容提取到指定的目标位置。例如:
1
| ADD source.file.tar.gz /temp
|
COPY命令
COPY
命令的基本语法为:
它仅用于将本地存储的文件或目录以现有格式复制到指定位置,不处理压缩文件的提取,也不能使用URL复制外部文件。例如:
1
| COPY /source/file/path /destination/path
|
核心代码
使用COPY
复制并解压文件
1 2 3
| 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
复制并解压文件
1
| ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/
|
最佳实践
- 优先使用
COPY
:如果只是简单地将本地文件或目录复制到构建上下文中,应始终使用COPY
,因为它比ADD
更透明。例如:
1 2 3
| COPY requirements.txt /tmp/ RUN pip install --requirement /tmp/requirements.txt COPY . /tmp/
|
这样可以确保每个步骤的构建缓存仅在特定所需文件更改时才失效。
- 避免使用
ADD
下载远程包:由于镜像大小很重要,强烈建议不要使用ADD
从远程URL获取包,而应使用curl
或wget
。例如:
1 2 3 4
| 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
提取本地压缩文件:ADD
的最佳用途是将本地tar文件自动提取到镜像中。例如:
常见问题
COPY
不支持URL源:COPY
命令不支持使用URL作为<src>
。COPY
不处理压缩文件:COPY
不会自动解压压缩文件,而是将其原样复制。对于instruction <src> <dest>
,如果<src>
是tar压缩文件且<dest>
不以斜杠结尾,ADD
会将<dest>
视为目录并解压<src>
到其中,而COPY
会将<dest>
视为文件并将<src>
写入其中。COPY
支持多阶段构建:从Docker 17.05开始,COPY
可以使用--from
标志在多阶段构建中从先前的构建阶段复制工件到当前构建阶段。例如:
1
| COPY --from=builder /app /app
|