docker-compose stop 默认等待10秒,需在docker-compose.yml的服务层级配置stop_grace_period(如45s)才生效,该设置仅对docker compose stop/down有效,且依赖应用正确处理SIGTERM信号。

docker-compose stop 默认等 10 秒,但 Docker Desktop 不改配置就无法延长
Docker Desktop 本身不提供图形界面调整 stop_grace_period 的入口,所有超时控制必须落在 docker-compose.yml 文件里——不是在设置面板、不是在偏好页、也不是靠重启 Desktop 生效。你改了 YAML,Docker Desktop 才会按新规则执行 docker-compose stop 或 docker compose down。
在 docker-compose.yml 中设置 stop_grace_period 才真正生效
这个字段必须写在具体服务(service)层级,不能放在顶层或 networks/volumes 下。它只对 docker compose stop 和 docker compose down 有效,对单个 docker stop 命令无效。
-
stop_grace_period: 45s是最常用写法,支持s、m单位,如2m表示 120 秒 - 若服务依赖数据库,建议 db 设为
30s,app 层设为60s,避免 app 还在等 db 响应就被强杀 - 该值不会影响容器启动,只约束“收到 SIGTERM 后最多等多久才发 SIGKILL”
- 如果服务里用了
init: true或自定义 PID 1(如tini),仍需确保主进程能转发信号,否则stop_grace_period形同虚设
为什么改了 YAML 还是秒退?检查这三处
常见现象:明明写了 stop_grace_period: 90s,执行 docker compose stop 却 2 秒就退出,STATUS 显示 Exited (137)。大概率是以下其一:
- 用的是旧版 Compose CLI:Docker Desktop 自带的
docker compose(v2)才支持该字段;若误用系统 PATH 里的docker-compose(v1),会静默忽略该配置 - 服务没真正监听
SIGTERM:Node.js 没写process.on('SIGTERM', ...),Java 应用没配spring.lifecycle.timeout-per-shutdown-phase,导致一收信号就直接 exit(0),根本没进清理逻辑 - 卷或网络挂载卡住:比如 PostgreSQL 容器绑定了宿主机目录且权限异常,
pg_ctl stop -m fast会 hang 住,超时后被强杀,日志里看不到shutting down字样
验证是否真走完优雅流程,别只看命令返回
停完不能只信终端输出,得查两处:
- 运行
docker ps -a,找对应容器的 STATUS 列:要是Exited (0)才算成功收尾;Exited (137)就是被 SIGKILL 干掉的,说明超时或信号未响应 - 立刻执行
docker logs,搜| tail -20 SIGTERM、gracefully、shutting down—— 如果一行都找不到,基本确认应用压根没注册信号处理器 - 临时加一句
command: sh -c "trap 'echo SIGTERM received' TERM; sleep 30"测试信号通路,再跑docker compose stop看终端是否打出那句提示
真正难调的从来不是配置项位置,而是让应用进程老老实实接住那个 SIGTERM 并撑够你写的秒数。











