停服信号与等待时间
compose 停止容器时会先发一个信号,等待一段时间,超时后改用强杀。默认发 SIGTERM、等 10 秒;用 stop_signal 可以换信号,用 stop_grace_period 可以延长等待。这两个字段决定应用有没有机会做收尾——关掉监听、排空在途请求、把缓冲区数据落盘。宽限期给得不够,收尾没做完就被强杀,日志截断与数据不完整往往就是这么来的。
基本信息
| 字段 | stop_signal: SIGTERM,stop_grace_period: 30s |
|---|---|
| 默认行为 | 发 SIGTERM,等待 10 秒 |
| 超时后果 | 发 SIGKILL 强杀,收尾逻辑被跳过 |
| 命令行对应 | docker stop -t 秒数 调整宽限期 |
典型使用场景
- 长事务服务停机:需要更多时间等待事务结束与连接排空
- 注册中心优雅下线:先注销实例再退出,避免流量打到已停止的节点
- 数据落盘保障:缓冲写与批量提交的服务需要时间刷盘
- 滚动发布窗口评估:宽限期越大,单个实例下线越慢,发布总时长要重算
- 排查日志截断:退出前的最后几行缺失,多为宽限期不足导致被强杀
配置与验证
配置与验证
services:
api:
image: app/api:1.4.2
stop_signal: SIGTERM # 应用捕获该信号做收尾
stop_grace_period: 30s # 给它 30 秒完成清理
# 命令行临时调整宽限期
docker compose stop api
# docker stop -t 30 <容器> 等价于给单个容器 30 秒信号与行为对照
| 配置 | 行为 | 适用情况 |
|---|---|---|
| 默认 SIGTERM | 应用可按需处理,属可捕获信号 | 绝大多数服务的正确选择 |
| SIGINT | 等同于终端中断,部分应用处理更早 | 本地开发调试为主 |
| SIGQUIT | 部分运行时会打印堆栈后退出 | 排查卡死问题时临时使用 |
| 超过宽限期 | 内核强杀进程,收尾被跳过 | 任何配置下都要避免走到这一步 |
应用不捕获信号时,收到 SIGTERM 会直接退出,宽限期再长也没用;治本方向是让应用处理信号并完成收尾。
批量停机时宽限期会叠加:多个实例串行停止,总时长可能明显超过预期,发布窗口要按实例数估算。