容器生命周期 #

容器状态详解 #

状态类型 #

text
┌─────────────────────────────────────────────────────┐
│                   容器状态类型                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  created    - 已创建,未启动                        │
│  running    - 正在运行                              │
│  paused     - 已暂停                                │
│  restarting - 正在重启                              │
│  exiting    - 正在退出                              │
│  exited     - 已退出                                │
│  dead       - 已死亡                                │
│  removing   - 正在删除                              │
│                                                     │
└─────────────────────────────────────────────────────┘

状态转换图 #

text
                    ┌──────────────┐
                    │   created    │
                    └──────┬───────┘
                           │ start
                           ↓
                    ┌──────────────┐
         unpause ──→│   running    │←── start
                    └──────┬───────┘
                           │
              ┌────────────┼────────────┐
              │ pause      │            │ stop/kill
              ↓            │            ↓
       ┌──────────────┐    │     ┌──────────────┐
       │    paused    │    │     │   stopped    │
       └──────────────┘    │     └──────┬───────┘
                           │            │
                           │            │ rm
                           │            ↓
                           │     ┌──────────────┐
                           └────→│   removed    │
                                 └──────────────┘

查看容器状态 #

bash
# 查看所有容器状态
docker ps -a --format "table {{.Names}}\t{{.Status}}"

# 查看特定状态容器
docker ps --filter "status=running"
docker ps --filter "status=exited"
docker ps --filter "status=paused"

# 查看容器详细状态
docker inspect --format '{{.State.Status}}' mycontainer
docker inspect --format '{{json .State}}' mycontainer | jq

重启策略 #

策略类型 #

策略 说明
no 不自动重启(默认)
on-failure[:max-retries] 退出状态非0时重启
always 总是重启
unless-stopped 除非手动停止,否则总是重启

配置重启策略 #

bash
# no - 不自动重启
docker run --restart=no nginx

# on-failure - 退出状态非0时重启
docker run --restart=on-failure nginx

# on-failure - 最多重启5次
docker run --restart=on-failure:5 nginx

# always - 总是重启
docker run --restart=always nginx

# unless-stopped - 除非手动停止
docker run --restart=unless-stopped nginx

更新重启策略 #

bash
# 更新运行中容器的重启策略
docker update --restart=always mycontainer

# 更新多个容器
docker update --restart=unless-stopped container1 container2

重启策略对比 #

text
┌─────────────────────────────────────────────────────────────────┐
│                     重启策略对比                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  场景: 容器退出                                                  │
│                                                                 │
│  ┌─────────────┬──────────┬──────────┬───────────────────────┐ │
│  │   策略      │ 手动停止 │ 崩溃退出 │ Docker服务重启        │ │
│  ├─────────────┼──────────┼──────────┼───────────────────────┤ │
│  │ no          │ 不重启   │ 不重启   │ 不重启                │ │
│  │ on-failure  │ 不重启   │ 重启     │ 重启(如果之前在运行)  │ │
│  │ always      │ 不重启   │ 重启     │ 重启                  │ │
│  │ unless-stop │ 不重启   │ 重启     │ 重启(除非手动停止过)  │ │
│  └─────────────┴──────────┴──────────┴───────────────────────┘ │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

健康检查 #

Dockerfile中定义 #

dockerfile
# 基本健康检查
HEALTHCHECK CMD curl -f http://localhost/ || exit 1

# 完整配置
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# 禁用健康检查
HEALTHCHECK NONE

参数说明 #

参数 默认值 说明
–interval 30s 检查间隔
–timeout 30s 超时时间
–start-period 0s 启动等待时间
–retries 3 重试次数

运行时配置 #

bash
# 运行时添加健康检查
docker run -d \
  --name mycontainer \
  --health-cmd="curl -f http://localhost:8080/health || exit 1" \
  --health-interval=30s \
  --health-timeout=3s \
  --health-retries=3 \
  --health-start-period=10s \
  myapp:v1.0

# 禁用健康检查
docker run --no-healthcheck myapp:v1.0

查看健康状态 #

bash
# 查看容器健康状态
docker inspect --format '{{.State.Health.Status}}' mycontainer

# 查看健康检查结果
docker inspect --format '{{json .State.Health}}' mycontainer | jq

# 查看最近一次健康检查
docker inspect --format '{{range .State.Health.Log}}{{.Output}}{{end}}' mycontainer

健康状态类型 #

text
┌─────────────────────────────────────────────────────┐
│                   健康状态                           │
├─────────────────────────────────────────────────────┤
│                                                     │
│  starting  - 容器启动中,等待start-period           │
│  healthy   - 健康检查通过                           │
│  unhealthy - 健康检查失败                           │
│  none      - 未配置健康检查                         │
│                                                     │
└─────────────────────────────────────────────────────┘

退出状态码 #

常见退出状态码 #

状态码 说明
0 正常退出
1 应用错误
125 Docker错误
126 命令无法执行
127 命令未找到
137 被SIGKILL终止(内存不足)
139 被SIGSEGV终止(段错误)
143 被SIGTERM终止

查看退出状态码 #

bash
# 查看容器退出状态码
docker inspect --format '{{.State.ExitCode}}' mycontainer

# 查看OOM状态
docker inspect --format '{{.State.OOMKilled}}' mycontainer

# 查看完整状态信息
docker inspect --format '{{json .State}}' mycontainer | jq

容器事件监控 #

docker events #

bash
# 实时监控容器事件
docker events

# 过滤特定事件
docker events --filter "type=container"
docker events --filter "event=start"
docker events --filter "event=stop"
docker events --filter "container=mycontainer"

# 指定时间范围
docker events --since "2024-01-01"
docker events --since "1h"
docker events --until "2024-01-02"

# 格式化输出
docker events --format '{{.Time}} {{.Type}} {{.Action}} {{.Actor.ID}}'

事件类型 #

text
┌─────────────────────────────────────────────────────┐
│                   容器事件类型                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  attach     - 附加到容器                            │
│  commit     - 提交镜像                              │
│  copy       - 复制文件                              │
│  create     - 创建容器                              │
│  destroy    - 删除容器                              │
│  detach     - 分离容器                              │
│  die        - 容器退出                              │
│  exec_create - 创建exec                             │
│  exec_start  - 启动exec                             │
│  export     - 导出容器                              │
│  kill       - 杀死容器                              │
│  oom        - 内存溢出                              │
│  pause      - 暂停容器                              │
│  rename     - 重命名容器                            │
│  restart    - 重启容器                              │
│  start      - 启动容器                              │
│  stop       - 停止容器                              │
│  top        - 查看进程                              │
│  unpause    - 恢复容器                              │
│  update     - 更新容器                              │
│                                                     │
└─────────────────────────────────────────────────────┘

容器等待 #

docker wait #

等待容器退出并返回退出状态码。

bash
# 等待容器退出
docker wait mycontainer

# 等待多个容器
docker wait container1 container2

# 在脚本中使用
exit_code=$(docker wait mycontainer)
echo "Container exited with code: $exit_code"

容器更新 #

docker update #

更新运行中容器的配置。

bash
# 更新资源限制
docker update --cpus=1.5 --memory=512m mycontainer

# 更新重启策略
docker update --restart=always mycontainer

# 更新环境变量(需要重建)
docker update --env-add NEW_VAR=value mycontainer

# 更新多个容器
docker update --cpus=1 container1 container2 container3

生命周期钩子 #

使用脚本处理生命周期 #

bash
#!/bin/bash
# container-lifecycle.sh

# 启动前钩子
pre_start() {
    echo "Preparing to start container..."
    # 执行初始化操作
}

# 启动后钩子
post_start() {
    echo "Container started, waiting for health check..."
    # 等待健康检查通过
    until [ "$(docker inspect --format='{{.State.Health.Status}}' mycontainer)" == "healthy" ]; do
        sleep 1
    done
    echo "Container is healthy!"
}

# 停止前钩子
pre_stop() {
    echo "Preparing to stop container..."
    # 执行清理操作
}

# 停止后钩子
post_stop() {
    echo "Container stopped"
    # 执行后处理
}

# 主流程
case "$1" in
    start)
        pre_start
        docker start mycontainer
        post_start
        ;;
    stop)
        pre_stop
        docker stop mycontainer
        post_stop
        ;;
    *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac

最佳实践 #

1. 使用合适的重启策略 #

bash
# 生产环境服务
docker run --restart=unless-stopped myapp

# 批处理任务
docker run --restart=on-failure:3 batch-job

# 开发环境
docker run --restart=no dev-app

2. 配置健康检查 #

dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

3. 优雅关闭 #

dockerfile
# 设置停止信号
STOPSIGNAL SIGTERM

# 设置停止超时
# 在docker run时使用 --stop-timeout
bash
# 设置停止超时
docker stop --time=30 mycontainer

4. 监控容器状态 #

bash
#!/bin/bash
# monitor-containers.sh

while true; do
    # 检查容器状态
    status=$(docker inspect --format='{{.State.Status}}' mycontainer)
    
    if [ "$status" != "running" ]; then
        echo "Container is not running: $status"
        # 发送告警或自动恢复
    fi
    
    # 检查健康状态
    health=$(docker inspect --format='{{.State.Health.Status}}' mycontainer 2>/dev/null)
    if [ "$health" == "unhealthy" ]; then
        echo "Container is unhealthy!"
        # 发送告警或自动恢复
    fi
    
    sleep 60
done

小结 #

本节学习了Docker容器的生命周期管理:

  • 容器状态类型和转换
  • 重启策略配置
  • 健康检查配置
  • 退出状态码
  • 容器事件监控

下一步 #

接下来,让我们学习 容器资源限制,了解如何限制容器的资源使用。