Files
docker_practice/07_dockerfile/7.3_add.md
T

229 lines
5.1 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.
## 7.3 ADD 更高级的复制文件
### 何时使用 ADD何时用 COPY
在开始前让我们直言不讳**在大多数情况下你应该使用 COPY而不是 ADD**
`ADD` `COPY` 基础上增加了两个额外功能它不是 `COPY` 的通用替代品但在少数场景中更合适
1. 自动解压 tar 压缩包有时你想复制一个 .tar.gz 本身 ADD 会意外地解压它
2. 支持从 URL 下载公开远程文件并可配合 `--checksum` 做校验
**实践中的建议**本地普通文件默认用 COPY本地 tar 自动解压或公开远程 artifact 下载并校验时用 ADD需要认证请求头重试或自定义解压流程时用 `RUN curl/wget`
### 7.3.1 基本语法
```docker
ADD [选项] <源路径>... <目标路径>
ADD [选项] ["<源路径>", ... "<目标路径>"]
```
`ADD` `COPY` 基础上增加了两个功能
1. 自动解压 tar 压缩包
2. 支持从 URL 下载文件
---
### 7.3.2 ADD vs COPY 详细对比
| 特性 | COPY | ADD |
|------|------|-----|
| 复制本地文件 | | |
| 自动解压 tar | | |
| 支持 URL | | (公开 artifact 可配合校验使用)|
| 行为可预测性 | | |
| 推荐程度 | **普通复制优先使用** | 解压本地 Git/公开远程 artifact |
> **笔者建议**普通复制始终优先 COPY只有当你明确需要 ADD 的额外语义时再使用 ADD并把意图写清楚
---
### 7.3.3 自动解压功能
#### 基本用法自动解压本地 tar
```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 /
```
#### 解压过程
```bash
ADD app.tar.gz /app/
├─ 识别 .tar.gz 格式
├─ 自动解压
└─ 内容放入 /app/
app.tar.gz 包含: /app/ 目录结果:
├── src/ ├── src/
│ └── main.py │ └── main.py
└── config.json └── config.json
```
---
### 7.3.4 URL 下载功能谨慎使用
#### 基本用法
```docker
## 从 URL 下载文件
ADD https://example.com/app.zip /app/app.zip
```
#### 使用边界
| 场景 | 建议 |
|------|------|
| 公开版本固定的远程 artifact | 使用 `ADD --checksum=sha256:... URL dest` |
| 需要认证请求头或复杂重试 | 使用 `RUN curl/wget` |
| 下载后需要复杂解压校验或清理 | 使用 `RUN curl/wget`把流程显式写出 |
| URL 内容可变但无校验 | 不建议直接写入 Dockerfile |
#### 推荐写法
```docker
## ✅ 公开 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` 的优势是控制力更强适合企业内网认证下载或复杂处理
---
### 7.3.5 修改文件所有者
```docker
ADD --chown=node:node app.tar.gz /app/
ADD --chown=1000:1000 files/ /app/
```
---
### 7.3.6 何时使用 ADD
#### 适合使用 ADD
```docker
## 解压本地 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
```
#### 不适合使用 ADD
```docker
## 复制普通文件(用 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/ # ✅ 保持原样
```
---
### 7.3.7 缓存行为
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/
```
---
### 7.3.8 最佳实践
#### 1. 默认使用 COPY
```docker
## ✅ 大多数场景使用 COPY
COPY . /app/
```
#### 2. 仅在需要解压时使用 ADD
```docker
## ✅ 自动解压场景
ADD app.tar.gz /app/
```
#### 3. 远程 artifact 使用 ADD 时必须固定校验值
```docker
## ✅ 公开 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
```
#### 4. 解压后清理
```docker
## 如果需要控制解压过程
COPY app.tar.gz /tmp/
RUN tar -xzf /tmp/app.tar.gz -C /app && \
rm /tmp/app.tar.gz
```
---