Docker 容器优雅退出需主进程(PID 1)直接响应 SIGTERM,避免 shell 启动导致信号丢失;应用须主动监听并执行清理逻辑;合理设置 stop-timeout(如 30s)保障资源释放。
让 Docker 容器真正优雅退出,核心是确保应用能收到 SIGTERM 信号并完成清理,而不是被 SIGKILL 强杀。这不单靠命令,更依赖容器内应用和启动方式的配合。
容器里 PID 1 的进程必须直接响应信号。常见陷阱是用 sh -c "myapp" 启动,导致 shell 占据 PID 1,而真正应用收不到信号。
CMD ["node", "server.js"](不是 CMD node server.js)exec 显式交出控制权:CMD exec node server.js
应用需主动监听 SIGTERM,并执行关机逻辑:拒绝新请求、完成当前任务、释放连接、保存状态。
process.on('SIGTERM', () => { cleanup(); process.exit(0); })
signal.Notify(c, syscall.SIGTERM) 阻塞等待,再调用 server.Shutdown()
Runtime.getRuntime().addShutdownHook() 注册清理动作默认 10 秒常不够——数据库刷盘、长事务、连接 draining 都可能超时。
docker run --stop-timeout=30 myapp
stop_grace_period: 30s
docker stop --time=30 container_name
不能只看容器停了,要看它怎么停的。
docker ps -a 中显示 Exited (0) 是正常退出;Exited (137) 表示被 SIGKILL 终止(通常因超时)docker logs container_name 搜索 SIGTERM、shutting down、gracefully 等关键词docker stop,观察应用是否打印“开始清理”再退出,而非立即中断