mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-10 11:54:37 +00:00
239 lines
4.3 KiB
Go
239 lines
4.3 KiB
Go
## 7.3 ADD 更高级的复制文件
|
||
|
||
### 基本语法
|
||
|
||
```docker
|
||
ADD [选项] <源路径>... <目标路径>
|
||
ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||
```
|
||
|
||
`ADD` 在 `COPY` 基础上增加了两个功能:
|
||
1. 自动解压 tar 压缩包
|
||
2. 支持从 URL 下载文件(不推荐)
|
||
|
||
---
|
||
|
||
### ADD vs COPY
|
||
|
||
| 特性 | COPY | ADD |
|
||
|------|------|-----|
|
||
| 复制本地文件 | ✅ | ✅ |
|
||
| 自动解压 tar | ❌ | ✅ |
|
||
| 支持 URL | ❌ | ✅(不推荐) |
|
||
| 行为可预测性 | ✅ 高 | ⚠️ 低 |
|
||
| 推荐程度 | ✅ **优先使用** | 仅解压场景 |
|
||
|
||
> 笔者建议:除非需要自动解压 tar 文件,否则始终使用 COPY。明确的行为比隐式的魔法更好。
|
||
|
||
---
|
||
|
||
### 自动解压功能
|
||
|
||
#### 基本用法(自动解压本地 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 /
|
||
```
|
||
|
||
#### 解压过程
|
||
|
||
```
|
||
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 复制文件](7.2_copy.md):基本复制操作
|
||
- [多阶段构建](7.17_multistage_builds.md):减少镜像体积
|
||
- [最佳实践](../16_appendix/16.1_best_practices.md):Dockerfile 编写指南
|