第一部分-Docker基础入门——05. 容器生命周期
05. 容器生命周期
1. 容器生命周期概述
容器从创建到销毁经历了多个状态,理解容器生命周期对于容器管理和故障排查至关重要。
┌─────────────────────────────────────────────────────────────┐ │ 容器生命周期状态图 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ docker create │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ Created │ │ │ │ 已创建 │ │ │ └──────┬──────┘ │ │ │ docker start │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Paused │ │ Running │ │ Restarting │ │ │ │ 已暂停 │◄──►│ 运行中 │◄──►│ 重启中 │ │ │ └─────────────┘ └──────┬──────┘ └─────────────┘ │ │ ▲ │ │ │ │ docker unpause │ docker stop/kill │ │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ Exited │ │ │ │ │ │ 已退出 │ │ │ │ │ └──────┬──────┘ │ │ │ │ │ docker rm │ │ │ │ ▼ │ │ │ │ ┌─────────────┐ │ │ │ │ │ Deleted │ │ │ │ │ │ 已删除 │ │ │ │ │ └─────────────┘ │ │ │ │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘2. 容器状态详解
2.1 七种容器状态
| 状态 | 说明 | 对应命令 |
|---|---|---|
| created | 已创建但未启动 | docker create |
| running | 正在运行 | docker start |
| paused | 已暂停(进程冻结) | docker pause |
| restarting | 正在重启 | 自动状态 |
| exited | 已退出/停止 | docker stop |
| dead | 已死亡(无法恢复) | 异常状态 |
| removing | 正在删除 | docker rm |
2.2 查看容器状态
# 查看所有容器状态dockerps-a# 查看特定容器状态dockerinspect--format='{{.State.Status}}'container_name# 查看完整状态信息dockerinspect container_name|grep-A15"State"# 查看状态详情dockerinspect--format=' Status: {{.State.Status}} PID: {{.State.Pid}} ExitCode: {{.State.ExitCode}} StartedAt: {{.State.StartedAt}} FinishedAt: {{.State.FinishedAt}} 'container_name3. 状态转换详解
3.1 Created → Running
# 创建容器(created 状态)dockercreate--namemyapp nginx# 查看状态dockerps-a|grepmyapp# STATUS: Created# 启动容器(转换为 running)dockerstart myapp# 查看状态dockerps|grepmyapp# STATUS: Up 5 seconds3.2 Running → Exited
# 方式1:正常停止(发送 SIGTERM)dockerstop myapp# 先发 SIGTERM,等待 10 秒后发 SIGKILL# 方式2:强制终止(发送 SIGKILL)dockerkillmyapp# 方式3:容器主进程退出# 当容器内 PID 1 进程退出时自动进入 exited# 指定停止等待时间dockerstop-t30myapp# 等待 30 秒3.3 Running → Paused
# 暂停容器(冻结所有进程)dockerpause myapp# 查看状态dockerps# STATUS: Paused# 恢复容器dockerunpause myapp3.4 退出码含义
# 查看退出码dockerinspect--format='{{.State.ExitCode}}'container_name# 常见退出码# 0: 正常退出# 1: 应用错误# 125: Docker 守护进程错误# 126: 命令无法执行# 127: 命令不存在# 128: 无效的退出参数# 137: 被 SIGKILL 杀死(OOM 或 docker kill)# 143: 被 SIGTERM 杀死(docker stop)# 255: 退出状态未知4. 生命周期钩子
4.1 健康检查(HEALTHCHECK)
# Dockerfile 中配置健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost/ || exit 1# 运行时配置健康检查dockerrun\--health-cmd="curl -f http://localhost/ || exit 1"\--health-interval=30s\--health-timeout=3s\--health-start-period=5s\--health-retries=3\nginx# 查看健康状态dockerinspect--format='{{.State.Health.Status}}'container_namedockerinspect container_name|grep-A10"Health"4.2 重启策略
# no: 不自动重启(默认)dockerrun--restart=no nginx# on-failure: 仅在非正常退出时重启dockerrun--restart=on-failure nginxdockerrun--restart=on-failure:3 nginx# 最多重启3次# always: 总是重启dockerrun--restart=always nginx# unless-stopped: 除非手动停止,否则总是重启dockerrun--restart=unless-stopped nginx# 更新已运行容器的重启策略dockerupdate--restart=always container_name# 查看重启策略dockerinspect--format='{{.HostConfig.RestartPolicy.Name}}'container_name5. 生命周期事件
5.1 容器事件监控
# 监听所有 Docker 事件dockerevents# 只监听容器事件dockerevents--filtertype=container# 监听特定容器事件dockerevents--filtercontainer=myapp# 监听特定事件类型dockerevents--filterevent=startdockerevents--filterevent=stopdockerevents--filterevent=diedockerevents--filterevent=kill# 监听退出的容器dockerevents--filterevent=die--filtercontainer=myapp# 获取历史事件dockerevents--since2024-01-01T00:00:00--until2024-01-02T00:00:005.2 常见事件类型
| 事件 | 说明 |
|---|---|
create | 容器创建 |
start | 容器启动 |
stop | 容器停止 |
kill | 容器被杀死 |
die | 容器退出(主进程结束) |
pause | 容器暂停 |
unpause | 容器恢复 |
restart | 容器重启 |
destroy | 容器销毁 |
oom | 内存溢出 |
exec_create | exec 创建 |
exec_start | exec 启动 |
6. 生命周期管理实践
6.1 优雅关闭
# 容器内信号处理# PID 1 进程需要正确处理 SIGTERM 信号# 测试信号传递dockerrun--rmalpinesh-c'trap "echo SIGTERM" TERM; sleep 60'# 在另一个终端执行dockerstop container_name# 确保应用监听 SIGTERM# Node.js 示例process.on('SIGTERM',()=>{console.log('收到 SIGTERM,正在关闭...');server.close(()=>{process.exit(0);});});# Python 示例importsignal def handle_sigterm(signum, frame): print('收到 SIGTERM,正在关闭...')sys.exit(0)signal.signal(signal.SIGTERM, handle_sigterm)6.2 容器自愈
# 使用重启策略实现自愈dockerrun-d--restart=always--nameresilient-app myapp# 模拟崩溃dockerexecresilient-appkill1# 容器会自动重启dockerps|grepresilient-app# 健康检查 + 重启dockerrun-d\--restart=always\--health-cmd="curl -f http://localhost:8080/health || exit 1"\--health-interval=10s\myapp6.3 资源清理自动化
# 定时清理退出的容器# crontab 配置02* * *dockercontainer prune-f# 清理退出超过24小时的容器dockercontainer prune--filter"until=24h"# 清理特定标签的容器dockerrm$(dockerps-a-q--filter"label=auto-cleanup=true")# 启动时自动删除dockerrun--rm-italpineecho"运行后自动删除"7. 故障排查
7.1 容器无法启动
# 1. 查看容器状态dockerps-a|grepcontainer_name# 2. 查看退出码dockerinspect--format='{{.State.ExitCode}}'container_name# 3. 查看日志dockerlogs container_name# 4. 查看详细信息dockerinspect container_name# 5. 尝试交互式启动dockerrun-it--entrypoint/bin/sh image_name# 6. 检查端口冲突dockerlogs container_name|grep"port already allocated"# 7. 检查挂载卷权限ls-la/host/mount/path7.2 容器频繁重启
# 查看重启次数dockerinspect--format='{{.RestartCount}}'container_name# 查看最后重启时间dockerinspect--format='{{.State.StartedAt}}'container_name# 查看 OOM 情况dockerinspect--format='{{.State.OOMKilled}}'container_name# 检查资源限制dockerstats container_name# 检查健康检查失败dockerinspect--format='{{.State.Health.Status}}'container_name# 查看事件历史dockerevents--filtercontainer=container_name--since1h7.3 僵尸进程问题
# 问题:容器内产生僵尸进程# 原因:PID 1 进程不处理 SIGCHLD 信号# 解决方案1:使用 tinidockerrun--init-dnginx# Dockerfile 中使用 tiniRUN apkadd--no-cache tini ENTRYPOINT["/sbin/tini","--"]CMD["nginx"]# 解决方案2:使用合适的 base image# 使用官方镜像通常已处理好 init 进程# 查看容器内进程dockerexeccontainer_namepsaux8. 生命周期最佳实践
✅ 设计原则
- 一个容器一个进程:保持单一职责
- 正确处理信号:优雅关闭服务
- 健康检查配置:确保服务可用性
- 合理的重启策略:避免无限重启
- 资源限制:防止 OOM 影响宿主机
✅ 运维实践
# 1. 生产环境推荐配置dockerrun-d\--nameapp\--restart=unless-stopped\--health-cmd="curl -f http://localhost/health"\--health-interval=30s\--health-timeout=3s\--health-retries=3\--init\--log-opt max-size=10m\--log-opt max-file=3\--cpus=1\--memory=512m\app:latest# 2. 优雅停机# 给容器足够时间处理现有请求dockerstop-t30container_name# 3. 监控告警dockerevents--filterevent=die--filterevent=oom# 4. 定期清理# 删除停止超过7天的容器dockercontainer prune--filter"until=168h"9. 生命周期监控脚本
#!/bin/bash# container-lifecycle-monitor.sh# 监控容器生命周期echo"=== 容器生命周期监控 ==="# 列出所有容器状态dockerps-a--format"table {{.Names}}\t{{.Status}}\t{{.Image}}"# 统计各状态数量echo-e"\n=== 状态统计 ==="forstatusincreated running paused exited dead;docount=$(dockerps-a--filterstatus=$status-q|wc-l)echo"$status:$count"done# 检查频繁重启的容器echo-e"\n=== 频繁重启检查 ==="dockerps-a--format"{{.Names}} {{.RestartCount}}"|awk'$2 > 5 {print $1 " 重启次数: " $2}'# 检查 OOM 的容器echo-e"\n=== OOM 检查 ==="forcontainerin$(dockerps-a-q);dooom=$(dockerinspect--format='{{.State.OOMKilled}}'$container)if["$oom"="true"];thenname=$(dockerinspect--format='{{.Name}}'$container)echo"$name: OOMKilled"fidone# 检查健康状态echo-e"\n=== 健康状态检查 ==="dockerps--format"{{.Names}} {{.Status}}"|grepunhealthy10. 常用命令速查
| 操作 | 命令 |
|---|---|
| 查看状态 | docker inspect --format='{{.State.Status}}' |
| 查看退出码 | docker inspect --format='{{.State.ExitCode}}' |
| 查看重启次数 | docker inspect --format='{{.RestartCount}}' |
| 监听事件 | docker events |
| 更新重启策略 | docker update --restart |
| 查看日志 | docker logs |
| 健康检查状态 | docker inspect --format='{{.State.Health.Status}}' |
11. 常见问题
Q1: 容器停止后数据会丢失吗?
容器停止后数据保存在容器层,删除容器会丢失。使用 Volume 可持久化。
Q2: 如何让容器在宿主机启动时自动启动?
dockerupdate--restart=always container_nameQ3: 如何优雅地停止容器内应用?
确保应用正确处理 SIGTERM 信号,或使用--stop-timeout参数。
12. 小结
- 容器有 7 种状态:created、running、paused、restarting、exited、dead、removing
- 通过 docker stop/kill 可控制容器退出
- 重启策略实现容器自愈
- 健康检查确保服务可用
- 信号处理实现优雅关闭
- 事件监控便于问题排查
