应优先使用 copy,仅在需自动解压或拉取远程文件时用 add;copy 行为明确、缓存稳定、更安全,add 虽支持解压和 url 但隐式逻辑多、风险高。

ADD 和 COPY 都用于将文件或目录从宿主机复制到镜像中,但 ADD 更“全能”也更隐晦,COPY 则更明确、更推荐用于常规复制场景。
功能范围不同:ADD 支持自动解压与远程 URL,COPY 仅支持本地路径
ADD 能识别特定压缩格式(tar.gz、tar.bz2、xz 等),若源文件是这些格式且目标路径为目录,Docker 会自动解压并展开内容。例如:
ADD app.tar.gz /app/ → 解压后内容落在 /app/ 下COPY 不具备该能力,遇到压缩包只会原样复制过去,不会解压。
此外,ADD 还支持直接从 URL 下载文件(如 ADD https://example.com/file.txt /tmp/),而 COPY 完全不支持网络源,只接受构建上下文内的本地路径。
语义与最佳实践:COPY 更清晰、更可控
Docker 官方文档明确建议:除非需要自动解压或拉取远程文件,否则一律使用 COPY。原因包括:
- COPY 行为可预测,无隐式解压逻辑,减少构建意外
- 镜像构建缓存更稳定 —— ADD 对远程 URL 的处理可能绕过缓存(因内容可能变化)
- 安全考虑:ADD 拉取远程资源时无法校验完整性,也不支持认证,易引入风险
- 团队协作中,COPY 更易理解,降低误用概率
缓存行为一致,但触发条件受源文件影响
两者都遵循 Docker 构建缓存机制:当某一层的 ADD 或 COPY 指令前后,源文件内容未变,且其他前置层也未变,则该层直接复用缓存。
注意点:
- ADD 若指向 tar 包,缓存依据的是压缩包本身内容,不是解压后文件树
- COPY 若指定整个目录(如 COPY ./src /app/src),只要其中任一文件变动,整条指令就失效,后续层全部重建
- 建议配合 .dockerignore 排除无关文件(如 node_modules、.git),避免缓存被无谓破坏
实际写法建议
多数情况下,优先写 COPY:
COPY package.json yarn.lock ./COPY src/ /app/src/
RUN yarn install
仅在确实需要解压部署包时用 ADD:
ADD release-v1.2.0.tar.gz /opt/app/完全避免用 ADD 拉取远程文件 —— 应改用 RUN wget/curl + rm 组合,便于控制和审计:
RUN curl -fsSL https://example.com/tool > /usr/local/bin/tool && chmod +x /usr/local/bin/tool











