CMD定义容器启动时默认命令,仅在docker run时生效且最后一个有效;三种写法:exec模式(推荐,主进程为程序本身,信号可接收)、为ENTRYPOINT提供参数模式(需配合exec格式ENTRYPOINT)、shell模式(经/bin/sh解析,支持环境变量但PID1为shell)。

CMD 指令定义容器启动时默认执行的命令,它不参与镜像构建过程,只在 docker run 时生效,且一个 Dockerfile 中仅最后一个 CMD 生效。它的三种写法对应不同执行机制和用途,关键区别在于是否经过 shell 解析、能否使用环境变量、是否适配 ENTRYPOINT。
CMD ["executable","param1","param2"](exec 模式,推荐)
这是最常用也最推荐的形式。Docker 直接调用指定可执行文件并传入参数,不经过 /bin/sh。主进程就是该程序(PID 1),信号能被正确接收,适合长期运行的服务。
- 环境变量不会自动展开,例如
["echo", "$HOME"]输出的是字面量$HOME - 如需使用环境变量,必须显式调用 shell:比如
["sh", "-c", "echo $HOME"] - 可单独作为容器入口,也可与 ENTRYPOINT 配合(此时只提供参数)
CMD ["param1","param2"](为 ENTRYPOINT 提供默认参数)
这种写法必须配合 ENTRYPOINT(且二者都需用 exec 格式),CMD 仅提供参数列表,实际执行的是 ENTRYPOINT + CMD 的组合。
- 例如:
ENTRYPOINT ["curl"]+CMD ["https://example.com"]→ 启动时执行curl https://example.com -
docker run myimg https://baidu.com会覆盖 CMD,最终执行curl https://baidu.com - 若 ENTRYPOINT 是 shell 格式,CMD 这种写法将无效,必须统一为 exec 格式
CMD command param1 param2(shell 模式)
该形式等价于 CMD ["sh", "-c", "command param1 param2"],由 shell 解析并执行,主进程是 /bin/sh,而非你写的命令本身。
- 支持直接使用环境变量,如
CMD echo $HOME会输出真实路径(如/root) - 因 PID 1 是 shell,子进程无法直接接收系统信号(如 SIGTERM),可能导致容器无法优雅退出
- 适合简单调试或一次性命令,不建议用于生产服务类容器
总结来说:要控制主进程、保障信号传递、提升可预测性,优先用 exec 格式;需要环境变量插值又不想写 shell 封装时,可选 shell 格式;而仅当明确配合 ENTRYPOINT 做参数抽象时,才用双数组无命令的写法。










