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
|