05. 容器生命周期1. 容器生命周期概述容器从创建到销毁经历了多个状态理解容器生命周期对于容器管理和故障排查至关重要。┌─────────────────────────────────────────────────────────────┐ │ 容器生命周期状态图 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ docker create │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ Created │ │ │ │ 已创建 │ │ │ └──────┬──────┘ │ │ │ docker start │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Paused │ │ Running │ │ Restarting │ │ │ │ 已暂停 │◄──►│ 运行中 │◄──►│ 重启中 │ │ │ └─────────────┘ └──────┬──────┘ └─────────────┘ │ │ ▲ │ │ │ │ docker unpause │ docker stop/kill │ │ │ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ Exited │ │ │ │ │ │ 已退出 │ │ │ │ │ └──────┬──────┘ │ │ │ │ │ docker rm │ │ │ │ ▼ │ │ │ │ ┌─────────────┐ │ │ │ │ │ Deleted │ │ │ │ │ │ 已删除 │ │ │ │ │ └─────────────┘ │ │ │ │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘2. 容器状态详解2.1 七种容器状态状态说明对应命令created已创建但未启动docker createrunning正在运行docker startpaused已暂停进程冻结docker pauserestarting正在重启自动状态exited已退出/停止docker stopdead已死亡无法恢复异常状态removing正在删除docker rm2.2 查看容器状态# 查看所有容器状态dockerps-a# 查看特定容器状态dockerinspect--format{{.State.Status}}container_name# 查看完整状态信息dockerinspect container_name|grep-A15State# 查看状态详情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# 启动容器转换为 runningdockerstart myapp# 查看状态dockerps|grepmyapp# STATUS: Up 5 seconds3.2 Running → Exited# 方式1正常停止发送 SIGTERMdockerstop myapp# 先发 SIGTERM等待 10 秒后发 SIGKILL# 方式2强制终止发送 SIGKILLdockerkillmyapp# 方式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 --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost/ || exit 1# 运行时配置健康检查dockerrun\--health-cmdcurl -f http://localhost/ || exit 1\--health-interval30s\--health-timeout3s\--health-start-period5s\--health-retries3\nginx# 查看健康状态dockerinspect--format{{.State.Health.Status}}container_namedockerinspect container_name|grep-A10Health4.2 重启策略# no: 不自动重启默认dockerrun--restartno nginx# on-failure: 仅在非正常退出时重启dockerrun--restarton-failure nginxdockerrun--restarton-failure:3 nginx# 最多重启3次# always: 总是重启dockerrun--restartalways nginx# unless-stopped: 除非手动停止否则总是重启dockerrun--restartunless-stopped nginx# 更新已运行容器的重启策略dockerupdate--restartalways container_name# 查看重启策略dockerinspect--format{{.HostConfig.RestartPolicy.Name}}container_name5. 生命周期事件5.1 容器事件监控# 监听所有 Docker 事件dockerevents# 只监听容器事件dockerevents--filtertypecontainer# 监听特定容器事件dockerevents--filtercontainermyapp# 监听特定事件类型dockerevents--filtereventstartdockerevents--filtereventstopdockerevents--filtereventdiedockerevents--filtereventkill# 监听退出的容器dockerevents--filtereventdie--filtercontainermyapp# 获取历史事件dockerevents--since2024-01-01T00:00:00--until2024-01-02T00:00:005.2 常见事件类型事件说明create容器创建start容器启动stop容器停止kill容器被杀死die容器退出主进程结束pause容器暂停unpause容器恢复restart容器重启destroy容器销毁oom内存溢出exec_createexec 创建exec_startexec 启动6. 生命周期管理实践6.1 优雅关闭# 容器内信号处理# PID 1 进程需要正确处理 SIGTERM 信号# 测试信号传递dockerrun--rmalpinesh-ctrap 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--restartalways--nameresilient-app myapp# 模拟崩溃dockerexecresilient-appkill1# 容器会自动重启dockerps|grepresilient-app# 健康检查 重启dockerrun-d\--restartalways\--health-cmdcurl -f http://localhost:8080/health || exit 1\--health-interval10s\myapp6.3 资源清理自动化# 定时清理退出的容器# crontab 配置02* * *dockercontainer prune-f# 清理退出超过24小时的容器dockercontainer prune--filteruntil24h# 清理特定标签的容器dockerrm$(dockerps-a-q--filterlabelauto-cleanuptrue)# 启动时自动删除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|grepport 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--filtercontainercontainer_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\--restartunless-stopped\--health-cmdcurl -f http://localhost/health\--health-interval30s\--health-timeout3s\--health-retries3\--init\--log-opt max-size10m\--log-opt max-file3\--cpus1\--memory512m\app:latest# 2. 优雅停机# 给容器足够时间处理现有请求dockerstop-t30container_name# 3. 监控告警dockerevents--filtereventdie--filtereventoom# 4. 定期清理# 删除停止超过7天的容器dockercontainer prune--filteruntil168h9. 生命周期监控脚本#!/bin/bash# container-lifecycle-monitor.sh# 监控容器生命周期echo 容器生命周期监控 # 列出所有容器状态dockerps-a--formattable {{.Names}}\t{{.Status}}\t{{.Image}}# 统计各状态数量echo-e\n 状态统计 forstatusincreated running paused exited dead;docount$(dockerps-a--filterstatus$status-q|wc-l)echo$status:$countdone# 检查频繁重启的容器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[$oomtrue];thenname$(dockerinspect--format{{.Name}}$container)echo$name: OOMKilledfidone# 检查健康状态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--restartalways container_nameQ3: 如何优雅地停止容器内应用确保应用正确处理 SIGTERM 信号或使用--stop-timeout参数。12. 小结容器有 7 种状态created、running、paused、restarting、exited、dead、removing通过 docker stop/kill 可控制容器退出重启策略实现容器自愈健康检查确保服务可用信号处理实现优雅关闭事件监控便于问题排查