4Docker 深度探索

Docker 容器

运行容器

容器生命周期命令

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第4章:Docker容器(Docker Containers)

一、导读

1.1 本章学习目标

容器是镜像的运行实例。本章全面讲解容器的生命周期管理、资源限制、网络配置、日志管理和健康检查。

本章的核心学习目标包括:

  • 掌握容器生命周期:创建、启动、停止、暂停、删除。
  • 配置资源限制:CPU、内存、PID 的限制。
  • 管理容器日志:日志驱动、日志轮转。
  • 配置重启策略:on-failure、always、unless-stopped。
  • 设置健康检查:HEALTHCHECK 指令和状态监控。

1.2 为什么本章如此重要

容器管理是日常运维的基本功。理解容器的生命周期、资源限制和健康检查,你才能构建可靠的容器化应用。

1.3 核心问题引导

docker stop 和 docker kill 的区别是什么?

容器内的 PID 1 进程有什么特殊之处?

如何限制容器使用的 CPU 和内存?

容器日志如何轮转?如何防止日志撑爆磁盘?

HEALTHCHECK 和 Liveness Probe 的关系是什么?


二、核心概念详解

2.1 容器生命周期

created → running → paused → running → stopped → deleted
bash
# 创建容器(不启动)
docker create --name myapp -p 3000:3000 node:18

# 启动容器
docker start myapp

# 暂停容器(冻结进程)
docker pause myapp

# 恢复容器
docker unpause myapp

# 停止容器(发送 SIGTERM,等待10秒后 SIGKILL)
docker stop myapp

# 强制停止(发送 SIGKILL)
docker kill myapp

# 删除容器
docker rm myapp

# 强制删除运行中的容器
docker rm -f myapp

2.2 容器进程模型

容器内的第一个进程是 PID 1。PID 1 有特殊职责:

  • 负责回收僵尸进程
  • 接收信号(SIGTERM、SIGINT)
dockerfile
# 推荐:使用 exec 形式,让应用成为 PID 1
CMD ["node", "server.js"]

# 不推荐:shell 形式会引入额外的 shell 进程
CMD node server.js

2.3 资源限制

bash
# CPU 限制
docker run --cpus=1.5 myapp           # 最多使用 1.5 核
docker run --cpu-shares=512 myapp     # 相对权重(默认1024)

# 内存限制
docker run --memory=512m myapp        # 最多 512MB
docker run --memory-swap=1g myapp     # 内存+swap 最多 1GB

# PID 限制
docker run --pids-limit=100 myapp     # 最多 100 个进程

# 组合使用
docker run -d \
  --cpus=1.5 \
  --memory=512m \
  --memory-swap=1g \
  --pids-limit=100 \
  --name limited-app myapp:1.0
bash
# 查看资源使用
docker stats --no-stream
# CONTAINER   CPU %   MEM USAGE / LIMIT   MEM %
# limited-app 0.5%    256Mi / 512Mi       50%

2.4 日志管理

bash
# 查看日志
docker logs myapp
docker logs -f myapp          # 实时跟踪
docker logs --tail 100 myapp  # 最后100行
docker logs --since 2h myapp  # 最近2小时

# 配置日志驱动
docker run -d \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  myapp

# 全局配置(daemon.json)
# {
#   "log-driver": "json-file",
#   "log-opts": {"max-size": "10m", "max-file": "3"}
# }

日志驱动类型:

  • json-file(默认):JSON 格式,支持轮转
  • syslog:发送到 syslog
  • journald:发送到 systemd journal
  • fluentd:发送到 Fluentd
  • awslogs:发送到 AWS CloudWatch

2.5 重启策略

bash
docker run -d --restart=no myapp           # 不自动重启(默认)
docker run -d --restart=on-failure:5 myapp # 失败时重启,最多5次
docker run -d --restart=always myapp       # 总是重启
docker run -d --restart=unless-stopped myapp  # 除非手动停止

2.6 健康检查

dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1
bash
# 查看健康状态
docker inspect --format='{{.State.Health.Status}}' myapp
# healthy / unhealthy / starting

# 查看健康检查日志
docker inspect --format='{{json .State.Health}}' myapp | jq

三、实战案例

3.1 完整的容器配置

bash
docker run -d \
  --name production-app \
  --cpus=2 \
  --memory=1g \
  --memory-swap=2g \
  --pids-limit=200 \
  --restart=unless-stopped \
  --log-driver json-file \
  --log-opt max-size=50m \
  --log-opt max-file=5 \
  -p 8080:8080 \
  -e NODE_ENV=production \
  -v app-data:/data \
  myapp:1.0

3.2 监控容器资源

bash
# 实时监控
docker stats

# 格式化输出
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

四、本章小结

容器生命周期:create → start → pause/unpause → stop/kill → rm。

PID 1 进程负责回收僵尸进程和接收信号。

资源限制:--cpus、--memory、--pids-limit。

日志管理:配置日志驱动和轮转策略。

健康检查:HEALTHCHECK 指令定期检测容器健康状态。


五、思考与练习

思考题

为什么容器内的 PID 1 进程很重要?如果 PID 1 退出会发生什么?

--memory-swap 设置为 -1 意味着什么?

如何防止容器日志撑爆磁盘?

HEALTHCHECK 失败后 Docker 会做什么?

练习题

创建一个带资源限制的容器,用 docker stats 监控。

配置日志轮转,生成大量日志验证轮转效果。

配置 HEALTHCHECK,模拟应用故障观察状态变化。

4/8Dock
0%