Qiu*_*ang 5 signals node.js npm docker alpine-linux
我阅读了一些Docker 和 Node.js 最佳实践文章,例如https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md或使用 Docker 容器化 Node.js Web 应用程序的 10 个最佳实践,或者Node 和 NPM 的 Dockerfile 良好实践。所有这些文章至少是在 2021 年写或更新的,我不列出 2021 年之前写的文章,但也有不少。
\n他们都反对CMD ["npm", "run", "start"]。主要原因是 npm 会吞掉SIGTERM 和 SIGINT 等退出信号,因此我的节点应用程序中的正常关闭代码将无法运行。
我猜旧的 npm 就是这种情况(虽然我没有测试它),但我已经测试了 node14+npm6 和 node16+npm8,我可以验证 npm6/8 不会吞下这些事件和我的优雅关闭代码正在运行。不确定这是否是因为 npm 修复了它。
\n因此,唯一的问题仍然是还有 1 个进程 npm 需要运行,即 NPM 作为PID 1运行。一些文章说问题是“PID 1 不会响应 SIGINT”,但据我证实,情况并非如此。
\n许多文章(例如这个nodejs文档)建议只是,CMD [ "node", "server.js" ]但也在https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals中说“Node.js进程运行为PID 1不会响应SIGINT(CTRL-C)和类似信号。”,即nodejs自己的文档自相矛盾(但我确实看到nodejs作为PID 1响应SIGINT)
CMD ["npm", "run", "start"]所以我对or 的问题感到困惑CMD [ "node", "server.js" ]
对于我的应用程序,还有 1 个考虑因素,我的 npm 脚本有预挂钩以使应用程序正确运行,我有prestartnpm 脚本可以工作npm start。所以目前我只是使用,CMD ["npm", "run", "start"]但我对如何在 docker 中启动我的节点应用程序的“最佳实践”感到困惑。
- - 更新 - -
\n我发现了 npm生命周期的这个已解决问题:将 SIGTERM 传播到子进程
\n所以他们确实修复了这个问题,但该问题的最新评论是在2017 年,其中说:“是的,这\xe2\x80\x99 不起作用,至少在 bash 中是这样;npm 在 shell 中运行其生命周期进程,而 bash 不\xe2 \x80\x99t 将 SIGTERM 转发给其子级。”
\n我意识到我只在我的 mac 和 CentOS 服务器以及基于 alpine 的 docker 上进行了测试。也可能是因为我在CMD中使用exec形式,而不是shell形式,所以我得到了退出信号。
\nNode.js 和 Kubernetes 的优雅关闭表示他们的 alpine 镜像没有使用 获得 SIGTERM npm start,而我在 alpine3.15 上测试,我可以得到。
为了解决 SIGINT 和 SIGTERM 的吞没问题,我这样做:
CMD [ "bash", "-c", "npm run db:migrate && node ./dist/server/index.js" ]
Run Code Online (Sandbox Code Playgroud)
npm run db:migrate && node ./dist/server/index.js我的内容在哪里npm start
| 归档时间: |
|
| 查看次数: |
2135 次 |
| 最近记录: |