Files
docker_practice/07_dockerfile/7.13_onbuild.md
T
yeasy a780127d48 fix(用词): 「其它」统一为「其他」(34 处 / 25 文件)
《现代汉语词典》与《中文技术文档写作风格指南》都以「其他」为规范词形;
本书基线是 90 处「其他」比 35 处「其它」,是集群里遗留最多的一本
(其余各书 0~4 处,blockchain_guide 已于 2026-08-05 统一过 47 处)。

其中 6 处在标题和目录上——`4.6 其它制作镜像的方式`、`第十七章 容器其它生态`、
`18.5 其它安全特性`——标题与 SUMMARY 条目**同批改写以保持一致**:
改动后 196 条目录名与各文件标题仍是 0 处不一致。

**`CHANGELOG.md` 里那一处刻意不动**:它是历史发布记录,改它等于改历史。

改动前后逐字符对称差:只有 34 个「它」变成「他」,无其他字符变化。
`check_project_rules` 202/202、`check_emphasis` 202/202、37 tests OK。
2026-08-24 13:18:05 -07:00

142 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
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.13 ONBUILD 为他人作嫁衣裳
### 7.13.1 基本语法
```docker
ONBUILD <其他指令>
```
`ONBUILD` 是一个特殊的指令,它后面跟的是其他指令(如 `RUN`,`COPY` 等),这些指令 **在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。
---
### 7.13.2 为什么需要 ONBUILD
`ONBUILD` 主要用于制作 **语言栈基础镜像** 或 **框架基础镜像**。
#### 场景:维护 Node.js 项目
假设你有多个 Node.js 项目,它们的构建流程都一样:
1. 创建目录
2. 复制 `package.json`
3. 执行 `npm install`
4. 复制源码
5. 启动应用
如果不使用 `ONBUILD`,每个项目的 Dockerfile 都要重复这些步骤,且通过 `COPY` 复制文件时,基础镜像无法预知子项目的文件名。
#### 使用 ONBUILD 的解决方案
**基础镜像 (my-node-base)**:
```docker
FROM node:22-alpine
WORKDIR /app
## 这些指令将在子镜像构建时执行
ONBUILD COPY package*.json ./
ONBUILD RUN npm install
ONBUILD COPY . .
CMD ["npm", "start"]
```
**子项目 Dockerfile**:
```docker
FROM my-node-base
## 只需要一行!
## 构建时会自动执行 COPY 和 RUN
...
```
---
### 7.13.3 执行机制
```bash
基础镜像构建:
Dockerfile (含 ONBUILD) ──build──> 基础镜像 (记录了 ONBUILD 触发器)
(指令未执行)
子镜像构建:
FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行触发器指令 ──> 继续执行子 Dockerfile
```
---
### 7.13.4 常见使用场景
#### 1. 自动处理依赖安装
```docker
## Python 基础镜像
ONBUILD COPY requirements.txt ./
ONBUILD RUN pip install -r requirements.txt
```
#### 2. 自动编译代码
```docker
## Go 基础镜像
ONBUILD COPY . .
ONBUILD RUN go build -o app main.go
```
#### 3. 处理静态资源
```docker
## Nginx 静态网站基础镜像
ONBUILD COPY dist/ /usr/share/nginx/html/
```
---
### 7.13.5 注意事项
#### 1. 继承性限制
`ONBUILD` 指令 **只会继承一次**。
- 镜像 A(含 ONBUILD)
- 镜像 B (FROM A) -> 触发 ONBUILD
- 镜像 C (FROM B) -> **不会** 再次触发 ONBUILD
#### 2. 构建上下文
子镜像构建时,`ONBUILD COPY . .` 中的 `.` 指的是 **子项目** 的构建上下文,而不是基础镜像的上下文。
#### 3. 不允许级联
`ONBUILD ONBUILD` 是非法的。你不能写 `ONBUILD ONBUILD COPY ...`。
#### 4. 可能会导致构建失败
由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求(例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。
---
### 7.13.6 最佳实践
#### 1. 命名规范
建议在镜像标签中添加 `-onbuild` 后缀,明确告知使用者该镜像包含触发器。
```bash
node:22-onbuild
python:3.12-onbuild
```
#### 2. 避免执行耗时操作
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作(如更新系统软件),这会让子镜像构建变得缓慢且不可控。
#### 3. 清理工作
如果 `ONBUILD` 指令产生了临时文件,最好在同一个指令链中清理,或者提供机制让子镜像清理。
---