07_dockerfile/7.3_add.md
在开始前,让我们直言不讳:在大多数情况下,你应该使用 COPY,而不是 ADD。
ADD 在 COPY 基础上增加了两个额外功能。它不是 COPY 的通用替代品,但在少数场景中更合适:
--checksum 做校验实践中的建议:本地普通文件默认用 COPY;本地 tar 自动解压或公开远程 artifact 下载并校验时用 ADD;需要认证、请求头、重试或自定义解压流程时用 RUN curl/wget。
ADD [选项] <源路径>... <目标路径>
ADD [选项] ["<源路径>", ... "<目标路径>"]
ADD 在 COPY 基础上增加了两个功能:
| 特性 | COPY | ADD |
|---|---|---|
| 复制本地文件 | ✅ | ✅ |
| 自动解压 tar | ❌ | ✅ |
| 支持 URL | ❌ | ✅ (公开 artifact 可配合校验使用) |
| 行为可预测性 | ✅ 高 | ⚠️ 低 |
| 推荐程度 | ✅ 普通复制优先使用 | 解压、本地 Git/公开远程 artifact |
笔者建议:普通复制始终优先 COPY;只有当你明确需要 ADD 的额外语义时再使用 ADD,并把意图写清楚。
## 自动解压 tar.gz 到目标目录
ADD app.tar.gz /app/
ADD 会识别并解压以下格式:
.tar.tar.gz / .tgz.tar.bz2 / .tbz2.tar.xz / .txz官方基础镜像通常使用 ADD 解压根文件系统:
FROM scratch
ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz /
ADD app.tar.gz /app/
│
├─ 识别 .tar.gz 格式
├─ 自动解压
└─ 内容放入 /app/
app.tar.gz 包含: /app/ 目录结果:
├── src/ ├── src/
│ └── main.py │ └── main.py
└── config.json └── config.json
## 从 URL 下载文件
ADD https://example.com/app.zip /app/app.zip
| 场景 | 建议 |
|---|---|
| 公开、版本固定的远程 artifact | 使用 ADD --checksum=sha256:... URL dest |
| 需要认证、请求头或复杂重试 | 使用 RUN curl/wget |
| 下载后需要复杂解压、校验或清理 | 使用 RUN curl/wget,把流程显式写出 |
| URL 内容可变但无校验 | 不建议直接写入 Dockerfile |
## ✅ 公开 artifact:使用 ADD 并固定校验值
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
RUN tar -xzf /tmp/app.tar.gz -C /app && rm /tmp/app.tar.gz
## ✅ 需要认证、请求头或特殊处理:使用 RUN + curl
RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app
ADD --checksum 的优势是缓存更精确,并且校验值直接绑定到 Dockerfile。RUN curl/wget 的优势是控制力更强,适合企业内网、认证下载或复杂处理。
ADD --chown=node:node app.tar.gz /app/
ADD --chown=1000:1000 files/ /app/
## 解压本地 tar 文件
FROM scratch
ADD rootfs.tar.gz /
## 解压应用包
ADD dist.tar.gz /app/
## 下载公开 artifact 并校验
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
## 复制普通文件(用 COPY)
ADD package.json /app/ # ❌
COPY package.json /app/ # ✅
## 需要认证或复杂下载逻辑(用 RUN + curl/wget)
ADD https://example.com/file / # ❌ 无法传认证信息,也没有显式处理
RUN curl -fsSL ... -o /file # ✅
## 需要保留 tar 不解压(用 COPY)
ADD archive.tar.gz /archives/ # ❌ 会解压
COPY archive.tar.gz /archives/ # ✅ 保持原样
ADD 可能导致构建缓存失效:
## 如果 app.tar.gz 内容变化,此层及后续层都需重建
ADD app.tar.gz /app/
RUN npm install
优化建议:
## 先复制依赖文件
COPY package*.json /app/
RUN npm install
## 再添加应用代码
ADD app.tar.gz /app/
## ✅ 大多数场景使用 COPY
COPY . /app/
## ✅ 自动解压场景
ADD app.tar.gz /app/
## ✅ 公开 artifact
ADD --checksum=sha256:<digest> https://example.com/file.tar.gz /tmp/file.tar.gz
## ✅ 认证下载或复杂处理
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
## 如果需要控制解压过程
COPY app.tar.gz /tmp/
RUN tar -xzf /tmp/app.tar.gz -C /app && \
rm /tmp/app.tar.gz