Files
docker_practice/image/dockerfile/add.md
2026-01-30 16:48:39 -08:00

222 lines
4.2 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADD 更高级的复制文件
## 基本语法
```docker
ADD [选项] <源路径>... <目标路径>
ADD [选项] ["<源路径>", ... "<目标路径>"]
```
`ADD` `COPY` 基础上增加了两个功能
1. 自动解压 tar 压缩包
2. 支持从 URL 下载文件不推荐
---
## ADD vs COPY
| 特性 | COPY | ADD |
|------|------|-----|
| 复制本地文件 | | |
| 自动解压 tar | | |
| 支持 URL | | 不推荐 |
| 行为可预测性 | | |
| 推荐程度 | **优先使用** | 仅解压场景 |
> 笔者建议除非需要自动解压 tar 文件否则始终使用 COPY明确的行为比隐式的魔法更好
---
## 自动解压功能
### 基本用法
```docker
# 自动解压 tar.gz 到目标目录
ADD app.tar.gz /app/
```
ADD 会识别并解压以下格式
- `.tar`
- `.tar.gz` / `.tgz`
- `.tar.bz2` / `.tbz2`
- `.tar.xz` / `.txz`
### 实际应用
官方基础镜像通常使用 ADD 解压根文件系统
```docker
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 下载功能不推荐
### 基本用法
```docker
# 从 URL 下载文件
ADD https://example.com/app.zip /app/app.zip
```
### 为什么不推荐
| 问题 | 说明 |
|------|------|
| 权限固定 | 下载的文件权限为 600通常需要额外 RUN 修改 |
| 不会解压 | URL 下载的压缩包不会自动解压 |
| 缓存问题 | URL 内容变化时不会重新下载 |
| 层数增加 | 需要额外 RUN 清理 |
### 推荐替代方案
```docker
# ❌ 不推荐:使用 ADD 下载
ADD https://example.com/app.tar.gz /tmp/
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
```
优势
- 一条 RUN 完成下载解压清理
- 减少镜像层数
- 更清晰的构建意图
---
## 修改文件所有者
```docker
ADD --chown=node:node app.tar.gz /app/
ADD --chown=1000:1000 files/ /app/
```
---
## 何时使用 ADD
### 适合使用 ADD
```docker
# 解压本地 tar 文件
FROM scratch
ADD rootfs.tar.gz /
# 解压应用包
ADD dist.tar.gz /app/
```
### 不适合使用 ADD
```docker
# 复制普通文件(用 COPY
ADD package.json /app/ # ❌
COPY package.json /app/ # ✅
# 下载文件(用 RUN + curl
ADD https://example.com/file / # ❌
RUN curl -fsSL ... -o /file # ✅
# 需要保留 tar 不解压(用 COPY
ADD archive.tar.gz /archives/ # ❌ 会解压
COPY archive.tar.gz /archives/ # ✅ 保持原样
```
---
## 缓存行为
ADD 可能导致构建缓存失效
```docker
# 如果 app.tar.gz 内容变化,此层及后续层都需重建
ADD app.tar.gz /app/
RUN npm install
```
**优化建议**
```docker
# 先复制依赖文件
COPY package*.json /app/
RUN npm install
# 再添加应用代码
ADD app.tar.gz /app/
```
---
## 最佳实践
### 1. 默认使用 COPY
```docker
# ✅ 大多数场景使用 COPY
COPY . /app/
```
### 2. 仅在需要解压时使用 ADD
```docker
# ✅ 自动解压场景
ADD app.tar.gz /app/
```
### 3. 不要用 ADD 下载文件
```docker
# ❌ 避免
ADD https://example.com/file.tar.gz /tmp/
# ✅ 推荐
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
```
### 4. 解压后清理
```docker
# 如果需要控制解压过程
COPY app.tar.gz /tmp/
RUN tar -xzf /tmp/app.tar.gz -C /app && \
rm /tmp/app.tar.gz
```
---
## 本章小结
| 场景 | 推荐指令 |
|------|---------|
| 复制普通文件 | `COPY` |
| 复制目录 | `COPY` |
| 自动解压 tar | `ADD` |
| URL 下载 | `RUN curl` |
| 保持 tar 不解压 | `COPY` |
## 延伸阅读
- [COPY 复制文件](copy.md)基本复制操作
- [多阶段构建](../multistage-builds.md)减少镜像体积
- [最佳实践](../../appendix/best_practices.md)Dockerfile 编写指南