Dockerfile 中 RUN 和 CMD 有什么区别?

RUN 在构建镜像时执行(装包、建目录,结果固化进镜像层),CMD 指定容器启动时的默认命令(可被 docker run 覆盖)。构建期用 RUN,运行期用 CMD。

最佳实践
Dockerfile 中 RUN 和 CMD 有什么区别?封面

一句话区别:RUN构建镜像时执行,命令结果(装的包、建的目录)作为新的镜像层永久固化;CMD容器启动时才生效,指定默认运行的命令,且可被 docker run 后面跟的参数整个覆盖。时机不同:RUN 属于 build,CMD 属于 run。

RUN:构建期执行

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl
RUN mkdir -p /app/logs

docker build 时每条 RUN 执行一次,结果存为新层。典型用途:装依赖、写配置、建目录、赋权限。

优化要点:多个关联命令用 && 合并成一条 RUN,减少层数;apt-get 装完顺手 rm -rf /var/lib/apt/lists/* 清理缓存,镜像更小。

CMD:运行期默认命令

CMD ["python", "app.py"]

docker run myimg 时执行;docker run myimg python debug.py 则 CMD 被替换。一个 Dockerfile 里写多条 CMD,只有最后一条生效。

对照记忆

RUN CMD
执行时机 docker build docker run(容器启动)
生效次数 每条都执行 只有最后一条
结果去向 固化成镜像层 不固化,仅启动进程
能否被覆盖 不能 run 参数整体覆盖

组合示例

FROM python:3.12-slim
RUN pip install flask gunicorn     # 构建期装依赖
COPY . /app
WORKDIR /app
CMD ["gunicorn", "-w", "4", "app:app"]   # 启动期默认命令

观测云对照

构建期动作影响运行期可观测性。 在 RUN 阶段装好 DataKit 需要的集成依赖、规划好日志输出目录(或直接 stdout),容器启动后日志采集与 APM 探针才能即插即用。

常见问题(FAQ)

Q:CMD 用 shell 形式还是 exec 形式?
A:推荐 exec 数组形式(CMD ["python","app.py"]),主进程为 PID 1,能收到 SIGTERM 优雅停机;shell 形式会裹一层 sh,信号传递有问题。

Q:ENTRYPOINT 和 CMD 又是什么关系?
A:ENTRYPOINT 定主程序、CMD 提供默认参数,详见本系列《Dockerfile 中 CMD 和 ENTRYPOINT 的区别》。

Q:RUN 执行失败会怎样?
A:构建立即中止报错;排查时可把复杂 RUN 拆小定位,或用 docker build --progress=plain 看完整输出。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台