CMD退出码即容器退出状态,由主进程返回值决定,影响docker ps、run结果及CI/CD;Shell形式经sh中转可能失真,Exec形式更可靠;常见码如0(成功)、1(错误)、137(OOM)、143(SIGTERM)。

CMD 指令的退出码直接决定容器的最终退出状态。当容器主进程(即 CMD 启动的命令)结束时,其进程退出码会被 Docker 捕获并作为整个容器的退出码。这个值会出现在 docker ps -a 的 STATUS 列中(如 Exited (1) 2 seconds ago),也会影响 docker run 命令的返回值,进而影响脚本判断、CI/CD 流水线成败或健康检查结果。
CMD 启动的进程就是容器的 PID 1
Docker 容器生命周期与 PID 1 进程强绑定:一旦 CMD 所执行的命令终止,容器立即停止,不会等待其他子进程。这意味着:
- 若 CMD 执行的是 shell 脚本,脚本最后一行命令的退出码即为容器退出码;
- 若 CMD 是
["sh", "-c", "cmd1 && cmd2"],则cmd2的退出码生效; - 若 CMD 启动一个长期运行的程序(如
nginx -g "daemon off;"),容器持续运行,直到该进程因错误、信号或主动退出而终止,此时它的退出码成为容器退出码。
Shell 形式与 Exec 形式对退出码的影响不同
CMD 支持两种写法,它们在信号传递和退出码捕获上存在关键差异:
-
CMD command arg1 arg2(Shell 形式):实际等价于
/bin/sh -c "command arg1 arg2"。此时 /bin/sh 是 PID 1,它负责执行命令并把退出码透传。但若命令被 SIGTERM 中断,shell 可能不转发信号给子进程,导致子进程无法优雅退出,退出码可能为 143(128+15)而非预期值; - CMD ["executable","param1","param2"](Exec 形式):executable 直接作为 PID 1 运行,信号可直达,退出码由该进程真实返回。推荐在生产环境使用此形式,确保退出行为可控。
常见退出码含义及调试建议
容器退出后,可通过 docker inspect <container> --format='{{.State.ExitCode}}' 查看精确退出码。典型场景包括:
- 退出码 0:主进程正常结束(如一次性脚本成功执行完毕);
- 退出码 1:通用错误(如命令未找到、语法错误、应用启动失败);
- 退出码 137:收到 SIGKILL(常因 OOM 被系统杀死,
docker stats可验证内存是否超限); - 退出码 143:收到 SIGTERM 后正常退出(如
docker stop触发,默认 10 秒超时后发 SIGKILL); - 非零但非标准退出码(如 2、127、255):需结合应用日志分析——用
docker logs <container>查看 stdout/stderr 输出,定位具体失败环节。
控制退出码的实用技巧
有时需显式设定容器退出行为,例如让健康检查更可靠或适配编排工具要求:
- 在 Shell 形式 CMD 中,用
|| exit N显式覆盖退出码(如CMD myapp || exit 2); - 使用
exec "$@"在入口脚本中接管 PID 1,确保信号透传和退出码准确(常见于 wrapper script 模式); - 避免在 CMD 中使用
&后台启动主进程(如CMD server &),否则 shell 立即退出,容器随之终止,退出码为 0,掩盖真实问题。










