RUN 指令是什么
RUN 在构建期执行命令:安装依赖、编译代码、生成配置。它的关键性质是每条 RUN 生成一个镜像层,因此安装与清理必须写在同一条指令里——文件一旦在某一层固化,后面再删也不会减小镜像体积。理解「一层一 RUN」是写高效 Dockerfile 的核心,也直接决定镜像推理与拉取的速度。
基本信息
| shell 形式 | RUN 命令,经 /bin/sh -c 执行,支持变量展开与管道 |
|---|---|
| exec 形式 | RUN ["可执行","参数"],不经 shell,无变量展开 |
| 分层规则 | 一条 RUN 一层,安装、清理、建目录尽量合并 |
| 构建缓存 | 命令文本不变即复用缓存,必要时用 --no-cache 跳过 |
| 调试技巧 | 命令开头加 set -eux,出错即停且回显每条命令 |
典型使用场景
- 安装系统依赖:apt 或 yum 装包后立即清理包缓存,控制体积
- 编译源码:在构建阶段完成编译,把产物复制到运行阶段
- 生成配置:构建期渲染模板,避免运行时再做初始化
- 创建用户与目录:提前建好非 root 用户与工作目录,提升安全性
- 校验下载:下载二进制时同步校验哈希,避免供应链风险
同层安装并清理
同层安装并清理
# 安装与清理写在同一层,否则被删的文件仍留在上一层历史里
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends curl ca-certificates; \
rm -rf /var/lib/apt/lists/*
# 放到下一条 RUN 里清理是无效的,体积不会变小
# RUN rm -rf /var/lib/apt/lists/*写法与影响对照
| 写法 | 优点 | 风险 |
|---|---|---|
| 合并安装与清理 | 体积小、层数少 | 命令较长需注意可读性 |
| 分开多条 RUN | 可读性好 | 层数多、中间文件残留 |
| exec 形式 | 不经 shell,行为可预测 | 无变量展开与管道 |
| 不使用 no-install-recommends | 省事 | 拉入大量无用依赖,体积膨胀 |
| 不锁依赖版本 | 总是拿到最新 | 构建不可复现,可能引入不兼容 |
不要在任何 RUN 里对生产镜像执行全量升级(如 apt-get upgrade):构建结果不可复现,还可能引入与业务不兼容的库版本。
构建缓存按指令文本匹配:只要 RUN 的命令字符串没变,即使上游文件已更新也会命中缓存。要拿最新结果时用 --no-cache,或调整命令文本触发重建。