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

152 lines
3.5 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.

# ONBUILD 为他人做嫁衣裳
## 基本语法
```docker
ONBUILD <其它指令>
```
`ONBUILD` 是一个特殊的指令它后面跟的是其它指令 `RUN`, `COPY` 这些指令**在当前镜像构建时不会执行**只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行
---
## 为什么需要 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:20-alpine
WORKDIR /app
# 这些指令将在子镜像构建时执行
ONBUILD COPY package*.json ./
ONBUILD RUN npm install
ONBUILD COPY . .
CMD ["npm", "start"]
```
**子项目 Dockerfile**
```docker
FROM my-node-base
# 只需要一行!
# 构建时会自动执行 COPY 和 RUN
```
---
## 执行机制
```
基础镜像构建:
Dockerfile (含 ONBUILD) ──build──> 基础镜像 (记录了 ONBUILD 触发器)
(指令未执行)
子镜像构建:
FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行触发器指令 ──> 继续执行子 Dockerfile
```
---
## 常见使用场景
### 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/
```
---
## 注意事项
### 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`会导致子镜像构建失败且错误信息可能比较隐晦
---
## 最佳实践
### 1. 命名规范
建议在镜像标签中添加 `-onbuild` 后缀明确告知使用者该镜像包含触发器
```
node:20-onbuild
python:3.12-onbuild
```
### 2. 避免执行耗时操作
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作如更新系统软件这会让子镜像构建变得缓慢且不可控
### 3. 清理工作
如果 `ONBUILD` 指令产生了临时文件最好在同一个指令链中清理或者提供机制让子镜像清理
---
## 本章小结
| 要点 | 说明 |
|------|------|
| **作用** | 定义在子镜像构建时执行的指令 |
| **语法** | `ONBUILD INSTRUCTION` |
| **适用** | 基础架构镜像Node, Python, Go |
| **限制** | 只继承一次不可级联 |
| **规范** | 建议使用 `-onbuild` 标签后缀 |
## 延伸阅读
- [COPY 指令](copy.md)文件复制
- [Dockerfile 最佳实践](../../appendix/best_practices.md)基础镜像设计