优先使用 COPY,仅在需自动解压本地 tar 包或拉取远程 URL 时才用 ADD;COPY 语义清晰、缓存稳定、权限保留且支持通配符,ADD 的额外功能有严格限制和风险。

优先用 COPY,只在明确需要自动解压或拉取远程 URL 时才考虑 ADD。
COPY 更安全、更可控
COPY 只做一件事:把构建上下文里的文件或目录原样复制进镜像。它不碰 URL,不解压归档,也不引入额外行为。这意味着:
- 语义清晰,Dockerfile 更易读、易维护
- 缓存稳定——只要源文件没变,这一层就能复用
- 权限和时间戳等元数据默认保留(可用
--chown调整属主) - 支持 Go 风格通配符,比如
COPY *.conf /etc/或COPY app-?.log /logs/
ADD 的特殊能力有明确边界
ADD 确实多两个功能,但每个都带使用前提:
- 自动解压本地 tar 包:仅限 gzip、bzip2、xz 格式,且必须是构建上下文内的文件(不能是 URL)
- 支持 HTTP/HTTPS URL 源:会触发网络下载,破坏构建可重现性,还可能因网络波动失败
注意:ADD 无法“边下载边解压”,URL 源不会被解压;只有本地 tar 文件才会被识别并展开。
别踩这些常见坑
实际写 Dockerfile 时容易忽略的细节:
-
路径必须在构建上下文中:COPY 和 ADD 都不能引用上下文外的绝对路径(如
/home/user/file.txt),否则构建报错 -
目标路径自动创建:即使
/app/config不存在,COPY config.yaml /app/config/也会成功 -
目录复制不含自身:
COPY src/ /dst/复制的是src里所有内容,不是把整个src文件夹放进去 - 缓存敏感度不同:ADD 对源文件内容变化更“敏感”,尤其涉及 tar 解压时,微小改动可能导致整层重建
一句话决策流程
看到要复制的文件:
- 是普通文件、脚本、配置、代码?→ 用
COPY - 是本地 .tar.gz 且希望自动解到镜像里?→ 用
ADD - 要从 GitHub raw 下载一个压缩包?→ 先用
RUN curl -sL ... | tar -xzf - -C /path,别用ADD - 不确定?→ 默认选
COPY,加个注释说明原因


















