# 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 最佳实践](../../15_appendix/best_practices.md):基础镜像设计