墨穗app.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v1.0.165 · 墨穗笔记
笔记

Notebase墨穗
静水流深,落墨成穗。

0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →

笔记

0
加载中...

工具

0

此页用于记录用户反馈问题后的每一次改进

关于

笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势

// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

docker stop 老等满 10 秒被强杀:多半是进程没接 SIGTERM

2026-09-02容器

容器里的服务每次发布重启都要等老半天,docker stop 按下去要卡十几秒才结束,看着就像 Docker 卡了。后来才明白这不是卡,是 Docker 在等进程自己退出,等满默认的 10 秒就发 SIGKILL 强杀。docker stop 的语义是:先给容器里 PID 1 的进程发 SIGTERM,让它优雅退出(关连接、刷缓存、存状态),超时没退就 SIGKILL。所以 stop 慢,本质是容器里的进程根本没正确处理 SIGTERM,或者信号压根没传到真正干活的进程那。

最常见的一种:Dockerfile 的 CMD 写的是 shell 形式,比如:

CMD node dist/index.js

这种写法实际启动的是 /bin/sh -c "node dist/index.js",PID 1 是那个 sh,node 是它的子进程。Docker 把 SIGTERM 发给 sh,sh 不会转发给 node,node 收不到信号自然不退出,sh 干等着,10 秒后 SIGKILL 把整棵进程树杀了。表现就是每次 stop 都精确卡 10 秒、容器退出码是 137。之前一直以为 137 都是内存超限被杀,其实 docker stop 强杀也是 137,两个场景别混。改成 exec 形式,让 node 直接当 PID 1:

CMD ["node", "dist/index.js"]

shell 就绕过去了,信号直达 node。如果 CMD 是脚本:

COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

脚本里真正拉起主进程的那行一定要写 exec,比如 exec node dist/index.js,否则脚本是 PID 1、node 变孤儿子进程,一样收不到信号。脚本里但凡有 node ... & 再 wait 的写法,更要小心,信号处理全得自己来。

第二个层面是进程收到 SIGTERM 之后有没有真正优雅退出。Node 默认收到 SIGTERM 是直接退的,但如果你自己注册了 handler 又没在回调里 process.exit,或者回调里做了异步清理没控制好时机,进程会挂在那不退出。标准写法:

const server = app.listen(3000)
function shutdown(signal) {
  console.log(signal + ' received, closing')
  server.close(() => process.exit(0))
  setTimeout(() => process.exit(1), 10000).unref()
}
process.on('SIGTERM', () => shutdown('SIGTERM'))
process.on('SIGINT', () => shutdown('SIGINT'))

server.close 等存量连接处理完再退出,setTimeout 是兜底防止回调死等,unref 让它不阻塞进程退出。Java 那边就是注册 shutdown hook,Python 是 signal 模块配 loop,道理一样,都是"收到信号、停止接收新请求、把在途的干完、自己退出"。

还有个容易漏的:容器里会有孤儿进程/僵尸进程的问题。如果主进程 fork 了一堆子进程干活又不 wait,子进程退成僵尸没人收,ps 里一堆 defunct,时间长了自己都感觉系统不对劲。Docker 其实有内置方案,docker run 加 --init 参数,或者 compose 里写 init: true,会在容器里塞一个 tini 当 PID 1,负责转发信号和回收僵尸。加上之后不用自己处理这些脏活。我现在的习惯是 compose 里无脑 init: true,省心很多。排查 stop 慢可以 docker inspect 看 State.ExitCode 是不是 137,再用 docker exec 进去 ps -ef 看 PID 1 到底是主程序还是 sh,基本一眼定位是"信号没传到"还是"收到了不退"。compose 场景下这个宽限对应 stop_grace_period 字段,默认也是 10 秒,需要给某个服务更长关闭时间就单独配:

services:
  app:
    image: 内部镜像
    stop_grace_period: 30s

还有一类进程要单独说:像 nginx 这种自己会处理信号的,直接当 PID 1 没问题,收到 SIGTERM 会把存量连接 gracefully 关掉再退。但如果你在容器里又套了一层 supervisord 或者 systemd 当 PID 1,那就要看这层有没有做信号转发,supervisord 默认会把 SIGTERM 转给它的子进程,但 systemd 当 PID 1 在容器里配置不对的话,信号经常卡在 systemd 那层不往下传。遇到容器里跑 systemd 的(有些打包成容器的服务这么干),docker stop 慢基本是常态,除了配 stop_grace_period 没太多好办法。

信号这块还有个生产环境才体会得到的点:容器被 orchestration 管理时,比如 docker compose 滚动更新、或者跑在 K8s 里被驱逐,都是先发 SIGTERM 等优雅退出,等不到才 SIGKILL。所以优雅退出写得好不好,直接决定发布时会不会断请求。理想情况是:进程收到 SIGTERM 后,从负载均衡/上游摘掉自己(或者靠健康检查失败被摘),停止接收新连接,把在途请求处理完,然后退出。我见过不少服务只写了 process.exit(0) 没做 server.close,结果升级瞬间正在处理的请求全被掐了,用户那边就是偶发 502。想要验证优雅退出到底有没有生效,可以自己手动模拟:docker stop 一个正在有请求的容器,同时盯着日志看有没有走到清理逻辑,走到且正常退出,说明处理链路是通的。

个别进程确实没法优雅退(比如老旧的闭源程序),可以 docker stop -t 30 临时把宽限拉长到 30 秒,算兜底。

相似推荐
服务器重启后 Docker 容器全没起来、顺序还乱?自启加依赖一次理清Docker 日志把磁盘写满,网站突然全挂?截断加限容一次配好docker compose 里 ${VAR} 到底读的哪个环境:.env、shell、env_file 优先级备忘容器里是普通用户,往 -v 挂的目录写文件老报 Permission deniedbuildx 打多架构镜像:arm64 在 x86 上构建,一路绿灯到部署才炸Node 镜像从 1.1G 瘦到 126M:多阶段构建一次改到位
编写使用方法
Markdown 格式 · Ctrl+Enter 确定
0 字新建笔记
欢迎回来
登录你的墨穗笔记账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属墨穗笔记
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

隐私提醒

取消
编辑工具
受控分享
为这篇笔记生成限时 / 带密码的临时链接
关闭