ADD 与 COPY 的差异
ADD 在 COPY 之上多了两项能力:可以从远程 URL 拉取文件,以及把本地 tar 归档自动解压到目标目录。这两项都是隐式行为,读 Dockerfile 的人不容易一眼看出发生了什么,所以官方建议默认用 COPY,只在确实需要自动解压时用 ADD。理解两者差异的重点不是「谁更好」,而是行为是否显式、结果是否可预测。
基本信息
| COPY | 只做本地复制,行为显式,源路径不能跳出构建上下文 |
|---|---|
| ADD 额外能力 | 远程 URL 下载;本地 tar 自动解压 |
| 自动解压范围 | 仅本地 tar 归档;URL 下载的文件不会解压 |
| 远程文件权限 | 下载结果默认 600 且属主为 root,与本地复制不同 |
| 完整性校验 | ADD 不校验远端内容,需要校验要自己实现 |
| 平台无关 | Linux 与 Windows 容器均支持,路径写法不同 |
典型使用场景
- 复制构建上下文里的文件与目录:一律优先 COPY
- 解压随代码一起提交的 tar 包:可用 ADD,但要清楚解压目标与属主规则
- 需要下载并校验的远程二进制:用 RUN curl 配合校验和,比 ADD 更可控
- 需要控制解压位置与权限:用 COPY 加 RUN tar 手动执行
- 镜像层优化:需要 URL 下载内容长期缓存时,ADD 的下载层缓存规则更容易误判
写法对照
写法对照
# COPY:只复制,不猜测意图
COPY ./app /srv/app
COPY --chown=10001:10001 ./config /etc/app
# ADD:本地 tar 会自动解压到目标目录(本例解压到 /srv/app 下)
ADD app.tar.gz /srv/app/
# ADD:远程 URL 拉取,不会自动解压,权限为 600
ADD https://example.com/releases/app.tar.gz /tmp/app.tar.gz
# 需要校验与可控解压时,显式写出来更清楚
# RUN curl -fsSL -o /tmp/app.tar.gz https://example.com/releases/app.tar.gz \
# && echo "<sha256> /tmp/app.tar.gz" | sha256sum -c - \
# && tar -xzf /tmp/app.tar.gz -C /srv/app行为差异速查
| 能力 | COPY | ADD |
|---|---|---|
| 本地文件复制 | 支持 | 支持 |
| 远程 URL 下载 | 不支持 | 支持(不校验、不解压) |
| 本地 tar 解压 | 不支持 | 支持 |
| 权限控制 | 可用 --chown 与 --chmod | 解压时属主取自归档内容 |
| 构建上下文限制 | 不能 ../ 跳出 | 本地源同样不能跳出 |
| 推荐度 | 默认首选 | 仅解压场景使用 |
ADD 的隐式解压结果由归档内容决定:归档里的属主、权限与目录结构会原样落到镜像里,发布前应确认解压出来的文件权限符合运行用户的要求。
用 ADD 下载远程文件时,镜像内容取决于远端当时的内容,构建不可复现;需要稳定产物就把文件放进制品库或本地上下文,再用 COPY。