📘 第04课:容器生命周期

基础 深入理解容器从创建到删除的完整生命周期,掌握容器管理的核心操作

🔄 容器生命周期全景

容器的生命周期是从 docker createdocker rm 的完整过程。理解每个状态转换是管理容器的关键:

docker createCreateddocker startRunning ↑ ↓ │ docker restart←──────────┘ │ ↓ │ docker pausePauseddocker unpause │ ↓ │ docker stopStopped │ ↓ └──────── docker start ←─┘ ↓ docker rmDeleted

容器状态一览

状态说明触发命令CPU/内存
created已创建但未启动docker create不占用
running正在运行docker start/run占用
paused暂停(冻结)docker pause内存占用,CPU释放
stopped已停止docker stop/kill不占用
restarting重启中重启策略触发切换中
dead无法删除的异常状态系统错误可能泄漏

🚀 创建与启动

docker create + docker start(两步法)

docker create 只创建容器不启动,适合需要预配置的场景:

# 创建容器(不启动)
docker create --name my-nginx -p 8081:80 nginx:alpine
# 输出容器ID:a1b2c3d4e5f6...

# 查看状态——Created
docker ps -a --filter name=my-nginx
# STATUS: Created

# 启动已创建的容器
docker start my-nginx
# my-nginx

# 确认运行
docker ps --filter name=my-nginx
# STATUS: Up 2 seconds
💡 docker run = docker create + docker start。两步法的优势在于可以在启动前修改容器配置。

docker run 常用参数

# 交互式运行(进入容器)
docker run -it --name my-alpine alpine:latest /bin/sh

# 后台运行
docker run -d --name my-redis -p 6379:6379 redis:alpine

# 运行后自动删除
docker run --rm alpine:latest echo "Hello Docker"

# 设置主机名和域名
docker run -d --name my-app \
  --hostname app-server \
  --dns 8.8.8.8 \
  nginx:alpine

# 指定重启策略
docker run -d --name my-api \
  --restart=on-failure:5 \
  -p 3000:3000 \
  node:20-alpine

重启策略对比

策略行为适用场景
no不自动重启(默认)临时任务、一次性命令
on-failure[:max]非零退出时重启可能临时失败的服务
always总是重启,包括Docker启动时核心服务
unless-stopped类似always,但手动stop后不随Docker启动可维护的服务

⏸ 暂停与恢复

docker pause 使用 Linux cgroups freezer 冻结容器内所有进程,不停止容器:

# 运行一个CPU密集型容器
docker run -d --name cpu-worker alpine:latest \
  sh -c "while true; do echo working; done"

# 查看CPU使用
docker stats cpu-worker --no-stream
# CPU %: 80-100%

# 暂停容器
docker pause cpu-worker
# cpu-worker

# 再次查看——CPU为0
docker stats cpu-worker --no-stream
# CPU %: 0.00%

# 状态变为Paused
docker inspect cpu-worker --format '{{.State.Status}}'
# paused

# 恢复容器
docker unpause cpu-worker
# cpu-worker
ℹ️ pause vs stop:暂停保留内存中的进程状态(类似"冻结"),恢复后程序从中断处继续;停止则发送 SIGTERM,进程优雅退出,内存释放。

🛑 停止与终止

docker stop(优雅停止)

# 优雅停止:发送SIGTERM,等待10秒后SIGKILL
docker stop my-nginx
# my-nginx

# 自定义超时时间(30秒)
docker stop -t 30 my-redis

docker kill(强制终止)

# 立即发送SIGKILL
docker kill my-nginx
# my-nginx

# 发送自定义信号
docker kill --signal=SIGHUP my-nginx

stop vs kill 对比

特性docker stopdocker kill
信号SIGTERM → (等待) → SIGKILLSIGKILL(默认)
优雅退出✅ 给应用清理时间❌ 立即终止
超时默认10秒可配置
数据安全应用可保存状态可能丢失未写入数据
适用场景日常运维容器无响应时

🔄 重启容器

# 重启 = stop + start
docker restart my-nginx
# my-nginx

# 带超时重启
docker restart -t 15 my-nginx

# 查看重启次数
docker inspect my-nginx --format '{{.RestartCount}}'
# 0

🗑 删除容器

# 删除已停止的容器
docker rm my-nginx
# my-nginx

# 强制删除运行中的容器(先kill再rm)
docker rm -f my-redis

# 删除时清理匿名卷
docker rm -v my-nginx

# 批量删除所有已停止容器
docker container prune
# WARNING! This will remove all stopped containers.

# 删除所有容器(包括运行中)
docker rm -f $(docker ps -aq)
⚠️ docker rm -f 会强制终止运行中的容器,可能导致数据丢失。生产环境应先 docker stopdocker rm

📊 容器状态查询

docker inspect 深度检查

# 查看容器完整状态
docker inspect my-nginx

# 提取特定字段
docker inspect my-nginx --format '{{.State.Status}}'
docker inspect my-nginx --format '{{.State.StartedAt}}'
docker inspect my-nginx --format '{{.State.ExitCode}}'
docker inspect my-nginx --format '{{.NetworkSettings.IPAddress}}'

# 查看容器进程
docker top my-nginx
# UID    PID    PPID   C   STIME   TTY   TIME       CMD
# root   1234   567    0   10:30   ?     00:00:00   nginx: master process

# 查看资源使用
docker stats my-nginx --no-stream
# CONTAINER   NAME       CPU%   MEM USAGE / LIMIT   MEM%
# a1b2c3d4     my-nginx   0.01%  2.1MiB / 1.94GiB    0.11%

docker events 实时监控

# 实时监听容器事件
docker events --filter type=container

# 按时间范围查询
docker events --since "2024-01-01" --until "2024-01-02"

# 过滤特定容器
docker events --filter container=my-nginx

🧪 实战:完整生命周期管理

让我们用一个Web应用体验完整的容器生命周期:

# 1. 创建容器
docker create --name lifecycle-demo \
  -p 8082:80 \
  --restart=unless-stopped \
  nginx:alpine
# ✅ 验证通过:容器已创建

# 2. 启动容器
docker start lifecycle-demo
# ✅ 验证通过:容器运行中

# 3. 验证服务可访问
curl -s -o /dev/null -w "%{http_code}" http://localhost:8082
# 200 ✅ 验证通过

# 4. 查看运行状态
docker ps --filter name=lifecycle-demo --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# NAMES             STATUS              PORTS
# lifecycle-demo    Up 10 seconds       0.0.0.0:8082->80/tcp

# 5. 暂停容器
docker pause lifecycle-demo
curl -s -o /dev/null -w "%{http_code}" http://localhost:8082
# 000 (连接被拒绝) ✅ 暂停后服务不可用

# 6. 恢复容器
docker unpause lifecycle-demo
curl -s -o /dev/null -w "%{http_code}" http://localhost:8082
# 200 ✅ 恢复后服务可用

# 7. 优雅停止
docker stop lifecycle-demo
docker ps -a --filter name=lifecycle-demo --format "{{.Status}}"
# Exited (0) 5 seconds ago ✅ 正常退出

# 8. 重新启动
docker start lifecycle-demo
# lifecycle-demo ✅ 验证通过

# 9. 清理
docker stop lifecycle-demo && docker rm lifecycle-demo
# lifecycle-demo ✅ 验证通过

🔧 故障排查

常见问题与解决

容器启动后立即退出(Exit Code 0) 前台进程结束导致容器退出。确保Dockerfile中使用 CMDENTRYPOINT 以前台模式运行,或用 docker run -it 交互运行调试。
容器 Exit Code 137 容器被 SIGKILL 终止,通常是内存不足(OOM Killer)或被 docker kill。检查 dmesg | grep -i oomdocker inspect --format '{{.State.OOMKilled}}'
容器 Exit Code 1 应用错误退出。使用 docker logs <container> 查看日志定位问题。
无法删除容器("container is paused") docker unpausedocker rm,或使用 docker rm -f 强制删除。
容器重启循环不停 重启策略 always 配合崩溃的应用会无限重启。用 docker logs 查看崩溃原因,临时用 docker update --restart=no 阻止重启。

调试命令速查

# 查看退出码
docker inspect <container> --format '{{.State.ExitCode}}'

# 查看完整日志
docker logs --tail 100 <container>

# 进入运行中容器
docker exec -it <container> /bin/sh

# 查看容器变更(相对镜像的文件系统变化)
docker diff <container>

# 查看容器资源限制
docker inspect <container> --format '{{.HostConfig.Memory}}'

📝 练习

  1. 生命周期实践:创建一个Alpine容器,依次执行 create → start → pause → unpause → stop → start → rm,记录每个阶段的状态变化
  2. 重启策略验证:分别用 --restart=no--restart=on-failure--restart=always 创建容器,手动停止后重启Docker服务,观察哪些容器自动启动
  3. 退出码分析:运行以下命令并查看退出码:
    docker run --rm alpine sh -c "exit 42"
    docker ps -a --filter "exited=42"
  4. 资源监控:运行一个容器,使用 docker stats 实时监控其CPU和内存使用

🏆 成就解锁:容器生命周期大师