CMD 是什么
声明容器启动时的默认命令或默认参数。运行容器时如果另外指定了命令,声明的内容会被整体替换;如果镜像里另有固定的入口程序,它则承担默认参数的角色。一个构建描述里写多条只有最后一条生效,这是一条容易被忽略的规则。
基本信息
| 作用 | 提供默认启动命令或默认参数 |
|---|---|
| 两种形式 | 参数数组形式与命令字符串形式 |
| 替换规则 | 运行时指定的命令整体覆盖它 |
| 多条声明 | 只有最后一条生效 |
| 常见搭配 | 与固定入口程序配合,作为可覆盖的默认参数 |
典型使用场景
- 给服务指定默认启动方式,让镜像开箱即可运行
- 作为入口程序的默认参数,允许运行时按需覆盖端口或日志级别
- 一次性任务镜像:默认执行一个动作,运行时换成别的命令做调试
- 多环境共用镜像:默认参数给常规值,特殊环境运行时替换
- 与脚本配合:默认命令指向启动脚本,脚本内部再按变量分支
常用示例
常用示例
CMD ["nginx", "-g", "daemon off;"] # 参数数组形式,推荐
CMD nginx -g "daemon off;" # 命令字符串形式,经解释器执行
CMD ["--port", "8080", "--log", "stdout"] # 作为入口程序的默认参数
# 运行时替换默认命令
# docker run --rm app/web:1.0 sh -c 'env | sort'启动命令的实际组合
| 运行方式 | 实际执行 | 说明 |
|---|---|---|
| 只给镜像名 | 入口程序加默认参数 | 镜像的默认行为 |
| 镜像名后跟参数 | 入口程序加新参数 | 默认参数被整体替换 |
| 覆盖入口程序 | 新程序加原默认参数 | 入口被替换,默认参数仍作为参数传入 |
| 覆盖入口并给参数 | 新程序加新参数 | 两者都被替换 |
| 命令字符串形式 | 解释器成为主进程 | 信号需要应用侧处理,建议优先用数组形式 |
写好默认命令的要点
- 优先用数组形式,参数透传与信号处理都更直接
- 确保命令在前台运行,后台自托管的启动脚本会让容器立刻退出
- 命令里引用的路径与工作目录保持一致,避免启动即报找不到文件
- 需要变量展开时显式使用解释器形式,不要指望数组形式帮你展开
- 把可替换的部分设计成参数,让同一镜像适应不同环境
命令字符串形式会让解释器成为容器内的一号进程,它不负责把终止信号转发给真正的应用,停止容器时容易出现等待超时后被强杀。
多条默认命令只有最后一条生效。写构建描述时如果前面写过一条又被覆盖,不要指望两条都能用上,检查方式是查看镜像配置里的最终值。