Dockerfile 中 COPY 和 ADD 命令有什么区别?

COPY 只做本地文件拷贝;ADD 额外支持 URL 下载和 tar 自动解压,但行为不透明。官方最佳实践:默认用 COPY,确需自动解压才用 ADD,下载文件用 RUN+curl 替代。

最佳实践
Dockerfile 中 COPY 和 ADD 命令有什么区别?封面

一句话区别:COPY 只能把构建上下文中的本地文件/目录拷进镜像,语义单一可预期;ADD 多两个能力——源可以是远程 URL、本地 tar 包会自动解压到目标目录。正因为 ADD 的"隐式魔法"(解压与否取决于文件类型)容易写出意外行为,官方建议一律优先用 COPY

语法相同,行为不同

COPY app.tar.gz /app/     # 原样拷贝,压缩包还是压缩包
ADD  app.tar.gz /app/     # 自动解压成目录内容
ADD  https://example.com/data.csv /data/   # 从 URL 下载

为什么推荐 COPY

  1. 行为透明:COPY 只有一种语义,镜像构建结果可预期
  2. 避免意外解压:本想拷个压缩包,ADD 却给解开了,镜像里凭空多一堆文件
  3. 缓存更稳:ADD 的 URL 形式会让构建缓存难以判断失效(远端内容变了 Docker 感知不到)

ADD 的合理使用场景

唯一公认合理的是本地 tar 自动解压

ADD nginx-1.25.tar.gz /usr/local/

下载文件的正确姿势

不要用 ADD <URL>,用 RUN 显式下载并顺手清理:

RUN curl -fsSL https://example.com/tool.tar.gz -o /tmp/tool.tar.gz \
    && tar -xzf /tmp/tool.tar.gz -C /opt \
    && rm /tmp/tool.tar.gz

下载、解压、清理在同一层完成,镜像不留下中间文件,失败也好排查。

常见问题(FAQ)

Q:COPY 能拷贝构建上下文之外的文件吗?
A:不能。源路径必须在构建上下文(build context)目录内;要拷外部文件先放进上下文或调整上下文范围。

Q:.dockerignore 对 COPY/ADD 有效吗?
A:有效。被 .dockerignore 排除的文件两者都拷不进去,用它排除 .git、node_modules、日志目录能显著加速构建。

Q:ADD URL 形式为什么没有缓存校验?
A:Docker 只能看到 URL 字符串没变就用缓存,感知不到远端文件内容变化,可能拿到旧文件——这是用 RUN+curl 的另一个理由。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台