bigywater.tech
Docker · 35

docker stop:SIGTERM 到 SIGKILL 的等待时间

docker stop 到底发什么信号、等多久?怎么让优雅退出的程序收到它认识的信号?这篇用一个会打印信号名、可以模拟清理耗时的 Python 程序实测,并发现这台 Docker Desktop 的默认宽限期并不是 10 秒。

3 秒
这台 Docker Desktop 的守护进程默认宽限期(default-stop-timeout),不带 -t 的 docker stop 最长等这么久
SIGQUIT / SIGUSR1
Dockerfile 的 STOPSIGNAL 与运行时 --stop-signal,后者覆盖前者
3112 ms / 0 vs 1131 ms / 137
清理要 3 秒时 -t 5 与 -t 1 的结果

默认信号

实测 · 本机执行输出
  默认:docker stop 用时 147 ms;ExitCode=0;日志:启动,PID 1 | 收到信号 SIGTERM | 清理完成,退出

docker stop 默认发 SIGTERM,装了处理程序的 PID 1 能收到并干净退出(ExitCode 0)。没装处理程序的 PID 1 收不到,见 c6。

改信号

实测 · 本机执行输出
  docker run --stop-signal SIGINT:docker stop 用时 113 ms;ExitCode=0;日志:启动,PID 1 | 收到信号 SIGINT | 清理完成,退出
  Dockerfile STOPSIGNAL SIGQUIT:docker stop 用时 117 ms;ExitCode=0;日志:启动,PID 1 | 收到信号 SIGQUIT | 清理完成,退出
  Dockerfile STOPSIGNAL SIGQUIT,运行时覆盖为 SIGUSR1:docker stop 用时 115 ms;ExitCode=0;日志:启动,PID 1 | 收到信号 SIGUSR1 | 清理完成,退出
  镜像里记录的 StopSignal:SIGQUIT

在 Dockerfile 里用 STOPSIGNAL,或运行时用 --stop-signal;两者同时存在时运行时的优先。需要某个信号才能优雅关闭的程序(比如 nginx 的 SIGQUIT)就要设。我这里用的是自己写的小程序,没有测真实的 nginx。

宽限期要够长

实测 · 本机执行输出
  清理 3 秒,docker stop -t 5:docker stop 用时 3112 ms;ExitCode=0;日志:启动,PID 1 | 收到信号 SIGTERM | 清理完成,退出
  清理 3 秒,docker stop -t 1:docker stop 用时 1131 ms;ExitCode=137;日志:启动,PID 1 | 收到信号 SIGTERM

清理要 3 秒的程序,宽限期 5 秒能干净退出,宽限期 1 秒则被 SIGKILL 打断(ExitCode 137,清理没做完)。

默认宽限期

实测 · 本机执行输出
  这个 Docker Desktop 的守护进程配置(虚拟机里的 /run/config/docker/daemon.json)里:"default-stop-timeout": 3,
  默认的 Config.StopTimeout = <nil>
  清理需要 15 秒时,docker stop(不带 -t):用时 3149 ms;ExitCode=137
  --stop-timeout 2 的 Config.StopTimeout = 2
  docker stop(不带 -t):用时 2123 ms;ExitCode=137
  --stop-timeout 2 再加 docker stop -t 4:用时 4188 ms(命令行参数优先)

常说 docker stop 默认等 10 秒,但这台 Docker Desktop 的守护进程配置里 "default-stop-timeout": 3,不带 -t 就是 3 秒(实测 3149 ms 后被杀,ExitCode 137)。优先级依次是 docker stop -t、--stop-timeout、守护进程的默认值;没有这个配置时的默认值是多少,我没有测。

分步演示

停止信号与宽限期
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。测试程序是 python:3.12-alpine 里的小脚本(PID 1,python -u,信号处理程序里 sleep WORK 秒再退出);用时用 Python time.time 测 docker stop 命令;守护进程配置是在虚拟机里只读查看 /run/config/docker/daemon.json(没有修改);实验后已删除容器和镜像
    • 没有验证:真实服务(nginx、postgres 等)的停止信号、Docker Desktop 以外的 Linux 宿主机默认宽限期、docker compose stop 的宽限期、Kubernetes 的 terminationGracePeriodSeconds、Windows 容器
    京ICP备2026067502号-1京公网安备11010502063487号