dockerd 重启时容器退出是因为其生命周期绑定于守护进程,默认会发送 SIGTERM 终止容器;启用 --live-restore 并配置 systemd KillMode=process 可保活容器进程。

dockerd 重启时容器为什么会退出
默认情况下 dockerd 进程退出,所有由它管理的容器会收到 SIGTERM,然后被强制终止——这不是“挂起”,是真·停机。根本原因在于容器生命周期完全绑定在 dockerd 的守护进程模型上:它负责创建、监控、回收容器进程,一旦主循环中断,子进程失去父监护,内核会清理孤儿进程(除非容器 PID=1 进程自己做了信号屏蔽或托管)。
常见错误现象:docker ps 空了,但 ps aux | grep your-app 还能看到残留进程;或者容器日志里出现 exited with code 137(OOM 或被 kill);更隐蔽的是 systemd 把 dockerd 当作普通服务重启,顺手把所有容器干掉了。
- 别依赖
systemctl restart docker做“平滑”操作——它本质是 stop + start,中间有间隙 - 容器若没设置
--restart=always,重启后不会自动拉起,哪怕dockerd恢复了 -
dockerd自身不支持热 reload 配置(比如/etc/docker/daemon.json改了必须重启进程)
用 dockerd 的 --live-restore 启动参数保活容器
--live-restore 是唯一能让容器在 dockerd 重启期间继续运行的官方机制。它让 dockerd 主动解耦自身生命周期与容器进程:当 daemon 进程退出时,容器的 init 进程(如 tini 或应用自身)变成孤儿,但 Linux 内核允许它们继续运行;新启动的 dockerd 会重新 attach 到已存在的容器进程树中。
使用场景:必须更新 daemon.json、升级 dockerd 二进制、或修复 daemon 崩溃问题,又不能接受业务中断。
- 必须在
/etc/docker/daemon.json中添加"live-restore": true,然后systemctl daemon-reload && systemctl restart docker—— 第一次启用需重启生效 - 启用后,
docker ps在 daemon 停止期间会报错Cannot connect to the Docker daemon,但容器进程仍在ps里可见 - 不兼容某些高级功能:如
docker stats在 daemon 停止期间不可用;容器日志驱动为journald时可能丢部分日志;Windows 容器不支持
systemd 侧要禁用 RestartSec 和限制 KillMode
即使开了 --live-restore,如果 systemd 配置不当,仍可能杀死容器。典型问题是 KillMode=control-group(默认值)会让 systemd 在 restart 前杀掉整个 cgroup,包括容器进程。
错误配置后果:容器进程被 systemd 强制 SIGKILL,--live-restore 失效。
- 修改
/etc/systemd/system/docker.service.d/override.conf,加入:[Service] KillMode=process RestartSec=5
-
KillMode=process表示只杀dockerd主进程,不碰它的子进程(即容器) -
RestartSec=5避免 daemon 启动失败时 systemd 过快重试,导致反复震荡 - 改完必须执行
systemctl daemon-reload && systemctl restart docker
验证 live-restore 是否真正生效
别只看 docker ps 是否恢复,要确认容器进程是否全程未中断。最直接的方式是观察 PID 和 uptime。
使用场景:上线前压测、变更后快速确认、排查偶发中断归因。
- 在容器内执行:
cat /proc/1/comm确认 PID=1 进程名(如sh、node);再记下cat /proc/1/stat | awk '{print $22}'(启动时间戳) - 触发
systemctl restart docker - 等 daemon 恢复后,再次检查同一容器的 PID=1 进程的
/proc/1/stat第 22 字段——如果数值没变,说明进程从未重启 - 补充验证:
docker inspect <cid> | jq '.State.Status'应始终为running,且.State.StartedAt时间戳不变
容易被忽略的是容器内应用自身的健康检查逻辑:有些服务监听 dockerd socket 断连就主动退出,这不属于 live-restore 能覆盖的范围,得改应用代码或加 wrapper 层兜底。










