如何让Docker中的Express应用优雅关闭并返回退出码0?
解决Docker容器退出码137问题
退出码137的本质是进程被强制终止:137 = 128 + 9,其中9对应SIGKILL信号。当执行docker stop时,Docker会先给容器内PID为1的进程发送SIGTERM信号,等待10秒默认超时后,如果进程仍未退出,就会发送SIGKILL强制杀死进程,此时容器就会返回退出码137。你的Node.js进程没有监听并处理SIGTERM信号,导致超时被强制终止。
解决方案:给Node.js添加优雅关闭逻辑
修改index.js,监听SIGTERM信号并主动关闭服务器后退出:
const express = require("express"); const app = express(); const port = 3000; // 保存服务器实例,用于后续关闭 let server; app.get("/", (req, res) => { res.send("Hello, Express!"); }); server = app.listen(port, () => { console.log(`Server is running on port ${port}`); }); // 捕获SIGTERM信号,优雅关闭服务 process.on("SIGTERM", () => { console.log("收到SIGTERM信号,开始优雅关闭服务器"); server.close(() => { console.log("服务器已成功关闭"); process.exit(0); // 主动以退出码0结束进程 }); });
验证步骤
- 重新构建镜像:
docker build -t express .
- 启动容器:
docker run --name app -p 5000:3000 -d express
- 停止容器:
docker stop app
- 查看退出状态:
docker ps -l
此时容器会立即停止无需等待10秒,退出码应为0。
补充说明
你的Dockerfile使用了CMD ["node", "index.js"]的exec格式,确保node进程是容器内的PID 1,能直接接收Docker发送的信号,无需额外调整Dockerfile。如果使用shell格式如CMD node index.js,PID 1会是shell进程,可能无法转发信号到node进程,这种情况才需要调整Dockerfile,但你的场景不需要。
内容的提问来源于stack exchange,提问作者Ivandez
相关产品推荐
相关产品推荐

