CMD 指令是什么
CMD 为容器提供默认的启动命令或参数,如果在 docker run 时指定了尾部命令,就会整体替换掉 CMD。一个 Dockerfile 里只有最后一条 CMD 生效,前面的会被静默忽略。当它与 ENTRYPOINT 同时存在时,CMD 的内容会作为参数追加到入口命令后面,这也是「入口固定、参数可覆盖」的标准写法。
基本信息
| 作用 | 默认启动命令或参数,运行时可被整体覆盖 |
|---|---|
| 唯一性 | 多条 CMD 仅最后一条生效,前面的不会报错但无效 |
| exec 形式 | CMD ["nginx","-g","daemon off;"],直接执行,信号可达 |
| shell 形式 | CMD nginx -g "daemon off;" 经 /bin/sh -c,信号先到 shell |
| 配合 ENTRYPOINT | CMD 的值作为 ENTRYPOINT 的追加参数 |
典型使用场景
- 定义默认启动:镜像开箱即可运行,无需在 run 时补命令
- 提供默认参数:配合 ENTRYPOINT 给出可被覆盖的启动参数
- 调试兼容:保留一条默认命令,方便直接 run 起容器排查
- 多环境复用:同一镜像用不同 CMD 参数跑不同模式的进程
- 配合编排:编排平台覆盖 CMD 以注入自身启动参数
推荐写法
推荐写法
# 推荐 exec 数组形式:应用直接作为 PID 1,能收到停止信号
CMD ["nginx", "-g", "daemon off;"]
# 与 ENTRYPOINT 配合时,CMD 只提供默认参数
# ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
# CMD ["nginx", "-g", "daemon off;"]
# 运行时覆盖示例:
# docker run myimage worker --queue=defaultCMD 与 ENTRYPOINT 组合
| 组合方式 | run 尾部命令的效果 |
|---|---|
| 只有 CMD | 整条替换 CMD |
| ENTRYPOINT 加 CMD | 作为参数追加给 ENTRYPOINT |
| 只有 ENTRYPOINT | 作为参数追加给 ENTRYPOINT |
| CMD 用 shell 形式 | 经 sh -c 执行,信号先到 shell |
| ENTRYPOINT 用 shell 形式 | CMD 参数会被忽略,是常见坑 |
想要「参数可覆盖、入口不可覆盖」就用 ENTRYPOINT 加 CMD 的组合;只有 CMD 时,run 的尾部参数会把启动命令整条替换掉,容易得到意料之外的行为。
使用 shell 形式启动时,docker stop 发送的停止信号先到 shell 而不是应用,应用收不到信号,往往等满超时时间后被强制杀死,表现为停机很慢、请求被中断。
需要给启动命令做前置处理时,把逻辑放在入口脚本里并保留 exec 转交,而不是把多条命令串进 CMD:命令行一旦被运行时覆盖,前置逻辑会整段跳过。