容器状态包括created、running、paused、stopped、exited五种,PID 1进程需主动处理信号,docker stop默认发SIGTERM并等待10秒后发SIGKILL,正确捕获信号可避免秒退等问题。

容器状态变化和信号传递是 Docker 运行时行为的核心机制,直接影响应用的启停、健康检查、优雅退出与资源回收。理解这些机制,能避免“容器秒退”“kill 不生效”“SIGTERM 被忽略”等常见问题。
容器生命周期的五种核心状态
Docker 容器的状态并非只有 running 和 exited 两种。实际由 libcontainer(现为 runc)在底层维护,CLI 展示的是简化视图。关键状态包括:
-
created:容器已创建但未启动(
docker create后),进程命名空间已分配,但主进程未运行; - running:初始进程(PID 1)正在运行,且未收到终止信号;
-
paused:通过
docker pause冻结所有进程(cgroup freezer 控制),内存仍驻留,CPU 时间片被挂起; - stopped:进程已终止(无论正常退出或被 kill),但容器文件系统和元数据仍保留;
-
exited:与 stopped 常混用,Docker CLI 中指“已停止且不可恢复运行”,exit code 可查(
docker inspect -f '{{.State.ExitCode}}')。
注意:restarting 是一种过渡态(如 restart policy 触发中),不是独立状态;dead 状态极少出现,通常表示清理失败或 runc 异常。
PID 1 的特殊性与信号转发规则
容器内 PID 1 进程承担双重角色:既是用户主程序,也是 init 进程。它不继承传统 Unix init 的信号处理能力,因此行为与普通进程不同:
- 默认情况下,Docker 不自动转发信号给子进程;只有 PID 1 收到信号才会响应;
-
docker stop默认发送 SIGTERM(10),等待 10 秒后发 SIGKILL(9)强制终止; - 若 PID 1 是 shell 脚本(如
/bin/sh -c 'app & wait'),需显式启用 job control(set -o monitor)并wait才能捕获子进程信号; - 使用
exec启动(如exec /app/server)可避免 shell 层级,让应用直连 PID 1,提升信号可达性。
常见信号与对应操作场景
除标准 POSIX 信号外,Docker 对部分信号做了语义映射:
- SIGTERM:推荐用于优雅关闭(释放端口、刷盘、断开连接)。应用应监听并主动退出,返回非零码表示异常;
-
SIGINT:等效于
Ctrl+C,docker attach时前台接收,docker exec -it中也有效; - SIGHUP:常用于重载配置(如 Nginx),但容器内需应用主动支持,Docker 不自动触发;
- SIGKILL:无法被捕获或忽略,直接终止进程。仅当 SIGTERM 失效或超时时由 Docker 强制发出;
- SIGUSR1/SIGUSR2:无预定义含义,完全由应用自定义(如日志轮转、调试 dump),需确保 PID 1 正确注册 handler。
调试与验证信号行为的方法
快速确认容器是否正确响应信号:
- 用
docker run -it --rm alpine sh -c 'trap "echo got TERM" TERM; sleep infinity'测试 SIGTERM 是否被捕获; - 执行
docker kill -s TERM后观察日志或 exit code; - 进入容器运行
ps auxf查看进程树,确认主进程是否为 PID 1; - 使用
docker inspect查看State.Status、State.Pid、State.OOMKilled等字段辅助判断异常原因。
不复杂但容易忽略。










