合并执行指令是什么
把安装、配置与清理写进同一条执行指令里。原因是层是增量叠加的:在上一层删掉的文件,仍然存在于上一层里,体积不会减少。只有把安装与清理放在同一层,临时文件才不会进入最终镜像,同时层数也更少。
基本信息
| 串联方式 | 用连接符把多条命令串成一条,前一条失败即中止 |
|---|---|
| 容错与打印 | 命令开头加上遇错中止与打印执行的设置,便于定位问题 |
| 清理位置 | 必须与安装同层,写在后续指令里等于没清理 |
| 层数影响 | 减少层数有助于缩小体积,但过度合并会让缓存粒度变粗 |
| 适用平台 | 所有使用构建描述的镜像构建流程 |
典型使用场景
- 安装系统依赖:更新索引、安装、删除索引写在同一条里
- 编译与清理:编译完成后删除临时产物,避免进入最终镜像
- 批量创建目录:创建多个目录并统一设置属主,减少层数
- 下载与解压:下载压缩包、解压、删除压缩包一条完成
- 多步配置:需要按顺序执行的初始化动作串成一条,避免中间失败留下半截状态
推荐写法
推荐写法
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends curl ca-certificates; \
rm -rf /var/lib/apt/lists/*
# 反例:清理写在另一条指令里,上一层文件仍在
RUN apt-get update && apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*合并与拆分的取舍
| 做法 | 优势 | 代价 |
|---|---|---|
| 合并安装与清理 | 体积小,层数少 | 局部改动会触发整条重建 |
| 按变更频率拆分 | 缓存命中率高,构建快 | 层数多一些,体积略增 |
| 全部合并成一条 | 层数最少 | 任何小改动都要重跑全部步骤 |
| 大量独立指令 | 调试方便 | 体积与层数都偏大 |
写合并指令的技巧
- 按变更频率分组,系统依赖一组、应用依赖一组、源码一组
- 安装与清理成对出现,中间不要插入与这两件事无关的步骤
- 命令开头加容错设置,中间失败能立刻停下并打印执行过程
- 换行书写提升可读性,注意续行符号的书写位置
- 把包管理器缓存目录清干净,常见位置是系统包管理器的索引目录
容错设置让中间命令失败即中止,并打印每条正在执行的命令。构建日志会变长,但排查失败比逐条猜要快得多。
把无关命令塞进同一条会让缓存粒度变粗:改一个不相关的配置就要重跑整层。合并的边界应按变更频率来划,而不是单纯追求层数最少。