run指令是dockerfile构建核心,需合并命令减少层数、及时清理缓存,并区分shell/exec格式;禁止在其中运行服务,应利用缓存将稳定操作前置。

RUN 指令是 Dockerfile 构建阶段最核心的命令,它直接决定镜像体积、安全性与构建效率。用得好,镜像精简、启动快、漏洞少;用得随意,容易导致层冗余、缓存失效、甚至引入安全风险。
优先合并多条命令,减少镜像层数
Docker 镜像是分层结构,每个 RUN 都会生成一个新层。层越多,镜像越臃肿,传输和加载越慢。关键是把关联操作写在一条 RUN 里,用 && 连接,并及时清理临时文件。
- ✅ 推荐写法(单层、无残留):
RUN apt-get update && apt-get install -y curl wget && rm -rf /var/lib/apt/lists/* - ❌ 避免写法(三层、残留缓存):
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
明确选择 Shell 或 Exec 格式,按需使用
RUN 有两种语法:Shell 格式(RUN command)和 Exec 格式(RUN ["cmd", "arg"])。它们行为不同,不能混用。
- Shell 格式默认走
/bin/sh -c,支持管道、变量扩展(如$HOME)、逻辑运算符(&&、||),适合常规安装配置。 - Exec 格式跳过 shell 解析,直接执行二进制,更精确可控,适合需要指定解释器或避免 shell 注入的场景,但不支持环境变量自动展开(需显式写
["/bin/bash", "-c", "echo $PATH"])。
避免在 RUN 中运行服务或长期进程
RUN 只用于构建时执行一次性命令,不是运行时环境。不要在 RUN 中启动 nginx、redis 或后台守护进程——这些属于容器运行阶段,应交给 CMD 或 ENTRYPOINT 处理。
- ❌ 错误示例:
RUN service nginx start && nginx -t(服务无法在构建中真正运行,且可能阻塞) - ✅ 正确做法:
只做配置验证、静态检查、预生成资源等;服务启动留给容器启动时。
利用构建缓存,合理安排指令顺序
Docker 构建会逐行比对 Dockerfile,一旦某行变化,其后所有 RUN 的缓存都会失效。所以要把变动少的操作(如系统包安装)放在前面,频繁修改的内容(如复制源码)放后面。
- 例如:先
RUN apt-get update && apt-get install...,再COPY . /app,最后RUN pip install -r requirements.txt。 - 如果
requirements.txt经常改,可单独把它 COPY 上来再 pip install,避免每次改代码都重装依赖。











