退出码由容器主进程终止时操作系统返回,Docker不支持直接配置;须确保应用为PID 1(用exec或直接CMD),按语义规范使用0/1/137/143等退出码,并结合HEALTHCHECK与restart策略实现自动化运维。
退出码本身不是“配置”出来的,而是容器主进程执行结束后由操作系统返回的整数值。docker 不提供直接设置退出码的指令,但你可以通过控制主进程行为、捕获信号、规范启动逻辑和配合健康检查,让退出码具备明确语义,从而支撑自动化运维判断。
确保主进程是 PID 1 并能正确返回退出码
容器状态完全取决于 PID 1 进程的退出码。如果用 sh -c "your-app" 启动,实际 PID 1 是 shell,而你的应用是子进程——shell 可能忽略子进程退出码或自行返回 0,导致失真。
- 用
exec your-app替代sh -c "your-app",让应用直接接管 PID 1,并真实传递其退出码 - Dockerfile 中避免无意义的 shell 封装:
❌ 错误写法:CMD ["sh", "-c", "node server.js"]
✅ 正确写法:CMD ["node", "server.js"]或ENTRYPOINT ["node"] && CMD ["server.js"] - 验证方式:
docker run --rm alpine sh -c 'exit 123'→ 再执行echo $?查看是否为 123;在容器中也可用docker inspect xxx | jq '.State.ExitCode'确认
按场景设计退出码语义并统一处理
不同退出码应对应可识别的运行状态,便于脚本或监控系统自动响应:
- 0:正常完成(如一次性任务成功)或服务就绪后长期运行(此时不应退出)
- 1:通用应用错误(配置加载失败、连接 DB 超时等),需告警 + 查日志
-
137:被 SIGKILL 终止 → 极大概率是 OOM(内存超限),应检查
docker inspect xxx | jq '.State.OOMKilled',调高-m限制 - 143:收到 SIGTERM 后正常退出 → 符合优雅终止预期,无需告警
- 125–127:Docker 命令层错误(镜像不存在、权限不足等),属于部署问题,CI/CD 流水线应拦截
结合 HEALTHCHECK 实现“状态+退出码”双维度判断
仅靠退出码无法反映运行中服务是否健康(比如进程活着但 API 返回 500)。HEALTHCHECK 提供独立于主进程生命周期的健康信号:
- 在 Dockerfile 中定义:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 CMD curl -f http://localhost:3000/health || exit 1 - 该命令返回 0 → 容器状态标记为 healthy;返回 1 → 标记为 unhealthy;不执行或超时也视为失败
- 退出码(来自主进程)反映“是否存活”,HEALTHCHECK 结果反映“是否可用”,两者互补。运维脚本可同时检查:
docker inspect xxx | jq '.State.Status, .State.ExitCode, .State.Health.Status'
用 restart 策略把退出码转化为运维动作
Docker 的 --restart 参数会依据退出码决定是否重启,这是自动化恢复的第一道闸口:
-
--restart=on-failure:3:仅当退出码非 0 时重启,最多重试 3 次(适合批处理或临时服务) -
--restart=unless-stopped:无论退出码是多少(包括 0)都重启,适用于长期 Web 服务(注意:0 退出通常意味着主进程不该退出,此时应排查为何没 stay alive) - 避免使用
always启动失败类容器(如镜像拉取失败退出码 125),它会无限循环拉取→失败→重启,压垮 daemon


















