docker stop 到底发什么信号、等多久?怎么让优雅退出的程序收到它认识的信号?这篇用一个会打印信号名、可以模拟清理耗时的 Python 程序实测,并发现这台 Docker Desktop 的默认宽限期并不是 10 秒。
默认: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、守护进程的默认值;没有这个配置时的默认值是多少,我没有测。