Dockerfile ADD 是什么
ADD 是 COPY 的增强版:除了复制文件,它还会把本地 tar 包自动解开,也能从 URL 拉取文件。这种隐式行为是它最大的问题——写 ADD 的人常常只想要一次复制,结果得到一个解压后的目录结构,或者一个权限为 600、内容还没校验的下载文件。除非确实需要自动解压本地 tar,否则一律用 COPY,让每一步做了什么一眼可见。
基本信息
| 语法 | ADD [--chown=用户:组] [--chmod=权限] 源 目标 |
|---|---|
| 额外能力 | 本地 tar 自动解压;支持从 URL 拉取文件 |
| 解压范围 | 仅本地 tar 及其 gz、bz2、xz 压缩形式;zip 不解,远程 tar 也不解 |
| URL 行为 | 只下载不解压、不校验完整性、失败不自动重试,文件权限为 600 |
| 缓存行为 | URL 目标的内容变化不会让缓存失效,容易构建出旧内容的镜像 |
| 建议 | 普通复制用 COPY,ADD 只用于明确的本地 tar 解压场景 |
典型使用场景
- 解压官方发布的 tar 包到固定目录,如把服务端程序放进运行镜像
- 把构建产物包解压到运行阶段,配合多阶段构建减少最终体积
- 迁移历史 Dockerfile 时保持原有行为,先确认解压结果再做优化
- 需要一次性拉取并解压时,改用 RUN 配合下载工具并校验校验和
- 解压后需要指定属主与权限:用 --chown 明确,避免默认 root 属主
使用示例
使用示例
ADD app-2026.tar.gz /opt/app/ # 本地 tar.gz 自动解压到目标目录
ADD --chown=app:app assets/ /srv/assets/ # 指定解出的文件属主(较新版本)
ADD config.yaml /etc/app/config.yaml # 普通文件:与 COPY 行为一致
ADD https://example.com/pack.tgz /tmp/ # 从 URL 下载,不会解压也不会校验
# 推荐替代:先校验再解压
# RUN curl -fsSL -o /tmp/p.tgz https://example.com/pack.tgz && echo "校验值 /tmp/p.tgz" | sha256sum -c - && tar -xzf /tmp/p.tgz -C /opt/appCOPY 与 ADD 对照
| 能力 | COPY | ADD |
|---|---|---|
| 本地普通文件 | 支持 | 支持,行为一致 |
| 本地 tar 自动解压 | 不支持 | 支持 gz、bz2、xz 等形式 |
| zip 压缩包 | 不解 | 也不解,落在镜像里的是压缩包 |
| 远程 URL | 不支持 | 支持,但不校验、不解压、权限受限 |
| 缓存失效判断 | 按本地内容 | URL 内容变化不会触发失效 |
URL 形式不校验完整性、失败不重试,属于典型的供应链风险入口:改用下载并校验校验和的做法,或把产物先放到构建上下文里。
远程 tar 不会被解压,这一点与本地 tar 的行为不同:需要解压时先在构建阶段下载,再用 RUN 解开。