Docker 容器优雅退出机制如何做

作者:袖梨 2026-08-14

Docker 容器优雅退出需主进程(PID 1)直接响应 SIGTERM,避免 shell 启动导致信号丢失;应用须主动监听并执行清理逻辑;合理设置 stop-timeout(如 30s)保障资源释放。

让 Docker 容器真正优雅退出,核心是确保应用能收到 SIGTERM 信号并完成清理,而不是被 SIGKILL 强杀。这不单靠命令,更依赖容器内应用和启动方式的配合。

确保主进程能接收 SIGTERM

容器里 PID 1 的进程必须直接响应信号。常见陷阱是用 sh -c "myapp" 启动,导致 shell 占据 PID 1,而真正应用收不到信号。

  1. 推荐在 Dockerfile 中使用 exec 格式: CMD ["node", "server.js"](不是 CMD node server.js
  2. 若需 shell 功能(如环境变量展开),可用 exec 显式交出控制权:CMD exec node server.js
  3. Go/Node.js/Python 等主流运行时默认支持 SIGTERM,但需确认未覆盖或屏蔽该信号

在代码中捕获并处理退出信号

应用需主动监听 SIGTERM,并执行关机逻辑:拒绝新请求、完成当前任务、释放连接、保存状态。

  1. Node.js 示例:process.on('SIGTERM', () => { cleanup(); process.exit(0); })
  2. Go 示例:用 signal.Notify(c, syscall.SIGTERM) 阻塞等待,再调用 server.Shutdown()
  3. Java 可通过 Runtime.getRuntime().addShutdownHook() 注册清理动作

合理设置停止宽限期

默认 10 秒常不够——数据库刷盘、长事务、连接 draining 都可能超时。

  1. 运行时指定:docker run --stop-timeout=30 myapp
  2. Docker Compose 中配置:stop_grace_period: 30s
  3. 手动停止时加参数:docker stop --time=30 container_name
  4. 避免设过长(如 5 分钟),影响部署节奏;也不宜过短(

验证是否真正优雅退出

不能只看容器停了,要看它怎么停的。

  1. 查退出码:docker ps -a 中显示 Exited (0) 是正常退出;Exited (137) 表示被 SIGKILL 终止(通常因超时)
  2. 翻日志:docker logs container_name 搜索 SIGTERMshutting downgracefully 等关键词
  3. 可加简单测试:启动后发 docker stop,观察应用是否打印“开始清理”再退出,而非立即中断

相关文章

精彩推荐