Docker: 性能调优与故障排查

最后更新:2026-08-26

生产环境容器出了问题——CPU 高?内存爆?IO 慢?你需要一套系统化的排查方法。

1. 你将学到


2. 一个凌晨告警的故事

(1) 痛点:API 延迟从 50ms 飙到 5s

生产环境 API 延迟从 50ms 飙升到 5s,用户大量投诉。Alice 用 docker stats 发现 CPU 没爆但 IO 等待极高,容器像"卡住了"一样。

(2) 系统化排查的解法

Alice 用 iostat 定位到日志驱动把磁盘 IO 打满了,切换日志驱动后恢复。

BASH
# Step 1: Check resource usage
docker stats --no-stream

# Step 2: Check host IO
iostat -x 1 5

# Step 3: Identify the bottleneck
docker system df -v

(3) 收益:5s→50ms,10 分钟恢复

从告警到修复只用了 10 分钟——系统化排查比"重启试试"高效 100 倍。


3. 性能排查决策树

(1) 四大瓶颈与对应工具

100%
graph TB
    START["Performance Issue"] --> CPU{"CPU 高?"}
    CPU -->|Yes| C1["docker stats<br/>top / htop"]
    CPU -->|No| MEM{"内存高?"}
    MEM -->|Yes| M1["docker stats<br/>/proc/meminfo"]
    MEM -->|No| IO{"IO 等待高?"}
    IO -->|Yes| I1["iostat -x<br/>docker system df"]
    IO -->|No| NET{"网络慢?"}
    NET -->|Yes| N1["iperf / ping<br/>tcpdump"]

(2) 常用排查工具

工具 作用 场景
docker stats 容器资源使用 CPU/内存/IO 概览
docker system df Docker 磁盘占用 磁盘满排查
docker events 容器事件流 OOM/重启/异常退出
docker logs 容器日志 应用错误
docker inspect 容器配置 状态/退出码/网络
iostat 磁盘 IO 统计 IO 瓶颈
iperf 网络带宽测试 网络瓶颈
nsenter 进入容器命名空间 高级调试

4. CPU 瓶颈排查

▶ 示例:docker stats 监控资源(难度⭐)

BASH
# Real-time stats for all containers
docker stats

# One-time snapshot
docker stats --no-stream

# Custom format
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

▶ 示例:stress 容器模拟 CPU 压力(难度⭐⭐)

BASH
# Run stress to simulate CPU load
docker run --rm --name stress-test \
  --cpus=1 \
  progrium/stress --cpu 1 --timeout 30s

# Monitor with docker stats (in another terminal)
docker stats stress-test --no-stream

5. 内存瓶颈排查

(1) 常见内存问题

现象 退出码 原因 解决
OOM Kill 137 超过 --memory 限制 增大限制或优化内存使用
内存泄漏 逐渐增长 应用 bug 分析 heap dump
缓存占用高 0 文件系统缓存 正常行为(可回收)

▶ 示例:模拟容器 OOM(难度⭐⭐⭐)

BASH
# Start container with 50 MB memory limit
docker run -d --name oom-test \
  --memory=50m \
  --restart=on-failure:3 \
  progrium/stress --vm 1 --vm-bytes 100M --timeout 10s

# Watch for OOM events
docker events --filter event=oom --since 1m

# Check exit code
docker inspect oom-test --format='ExitCode: {{.State.ExitCode}}, OOMKilled: {{.State.OOMKilled}}'

6. 磁盘 IO 瓶颈排查

▶ 示例:docker system df 磁盘分析(难度⭐⭐)

BASH
# Show Docker disk usage
docker system df

# Detailed breakdown
docker system df -v
💻 输出:

TEXT 📖 仅展示
TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
Images          12      5       4.2GB     2.8GB (66%)
Containers      8       3       350MB     280MB (80%)
Local Volumes   5       3       1.2GB     500MB (41%)
Build Cache     45      0       800MB     800MB (100%)

▶ 示例:磁盘清理策略(难度⭐⭐)

BASH
# Remove unused data (images, containers, volumes, build cache)
docker system prune

# More aggressive: remove all unused images (not just dangling)
docker system prune -a

# Remove build cache only
docker builder prune

# Remove volumes (WARNING: deletes data)
docker volume prune

(1) 存储驱动对比

驱动 性能 稳定性 推荐
overlay2 ✅ 稳定 ✅ 默认推荐
aufs ⚠️ 旧内核 ❌ 已弃用
devicemapper ⚠️ 配置复杂 ❌ 不推荐
zfs ✅ 稳定 特定场景
btrfs ⚠️ 不稳定 ❌ 不推荐

7. 网络排查

▶ 示例:iperf 网络带宽测试(难度⭐⭐⭐)

BASH
# Start iperf3 server in a container
docker run -d --name iperf-server --network host networkstatic/iperf3 -s

# Run iperf3 client from another container
docker run --rm --network host networkstatic/iperf3 -c localhost -t 10

# Test between two containers on different networks
docker run --rm --network app-net networkstatic/iperf3 -c db -t 5

▶ 示例:docker events 事件追踪(难度⭐⭐)

BASH
# Monitor container lifecycle events
docker events --filter type=container

# Filter for specific events
docker events --filter event=oom --filter event=die --filter event=restart

# Time-based filter
docker events --since "2024-01-15T03:00:00" --until "2024-01-15T04:00:00"

8. 高级调试:nsenter

▶ 示例:nsenter 进入容器命名空间(难度⭐⭐⭐)

BASH
# Get container's main PID
PID=$(docker inspect --format='{{.State.Pid}}' myapp)

# Enter the container's network namespace for debugging
nsenter -t $PID -n tcpdump -i eth0 -c 100 port 8080

# Enter the container's process namespace
nsenter -t $PID -p -m strace -p 1
💡 提示: nsenter 比 docker exec 更底层——它直接进入容器的 Linux namespace,不需要容器内有 shell。适合调试 scratch/distroless 镜像。


9. 常见故障与解决对照表

故障现象 排查命令 常见根因 解决方法
容器频繁重启 docker ps -a + docker logs OOM / 应用崩溃 增大内存 / 修复 bug / restart 策略
磁盘空间满 docker system df -v 日志/镜像/卷堆积 docker system prune + 日志轮转
网络连接超时 docker exec ping + nc 网络配置错误 检查网络/DNS/端口
构建缓慢 docker build --progress=plain 缓存失效 调整 COPY 顺序
容器启动失败 docker logs + docker inspect 配置错误/依赖缺失 修复配置/检查依赖
IO 等待高 iostat -x 日志驱动/大量写入 切换日志驱动/优化写入

10. 完整示例:容器 OOM 排查与修复

BASH
# ============================================
# Complete walkthrough: OOM diagnosis and fix
# Covers: stats, events, logs, inspect, fix
# ============================================

# 1. Deploy the problematic container
docker run -d \
  --name leaky-app \
  --memory=100m \
  --restart=on-failure:5 \
  -p 8080:8080 \
  myapp:1.0

# 2. Monitor resource usage
docker stats leaky-app --no-stream

# 3. Simulate memory leak (trigger OOM)
docker exec leaky-app python -c "
import itertools
data = []
for i in itertools.count():
    data.append('x' * 1024 * 1024)  # 1 MB each
    if i % 10 == 0:
        import time; time.sleep(0.1)
"

# 4. Capture OOM event
docker events --filter container=leaky-app --filter event=oom --since 1m

# 5. Check exit code and OOM status
docker inspect leaky-app --format='
ExitCode: {{.State.ExitCode}}
OOMKilled: {{.State.OOMKilled}}
Memory Limit: {{.HostConfig.Memory}}
'

# 6. Check application logs for memory patterns
docker logs --tail 100 leaky-app 2>&1 | grep -i "memory\|alloc\|oom"

# 7. Fix: increase memory limit
docker stop leaky-app && docker rm leaky-app
docker run -d \
  --name leaky-app \
  --memory=512m \
  --restart=on-failure:5 \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  -p 8080:8080 \
  myapp:1.0

# 8. Set up monitoring alert
docker events --filter event=oom | while read event; do
  echo "ALERT: OOM detected at $(date)" >> /var/log/docker-alerts.log
done

❓ 常见问题

Q 容器性能问题怎么分层排查?
A 四步法:① docker stats 看 CPU/内存/IO 概览;② 根据最高指标选工具(CPU→top,内存→smem,IO→iostat,网络→iperf);③ 定位到具体容器/进程;④ 分析应用日志找根因。
Q overlay2 和 aufs 哪个好?
A overlay2 更好,是 Docker 默认和唯一推荐的存储驱动。aufs 已弃用,Docker 24+ 不再支持。overlay2 性能更好、实现更简单、社区支持更活跃。
Q 容器磁盘空间满了怎么清理?
A docker system df -v 看什么占最多 → 对应清理:① 镜像:docker image prune -a;② 构建缓存:docker builder prune;③ 容器:docker container prune;④ 卷:docker volume prune(谨慎,会删除数据);⑤ 全部:docker system prune -a
Q 容器 IO 慢怎么排查?
Adocker stats 看 BlockIO 列;② 主机 iostat -x 1 看 %util 和 await;③ docker system df -v 看存储驱动占用;④ 常见原因:日志驱动写满磁盘、overlay2 层过多、bind mount 到慢磁盘。
Q 怎么给容器做网络延迟测试?
A 用 iperf3:服务端容器 iperf3 -s,客户端容器 iperf3 -c server。测试吞吐量和延迟。容器间测试需在同一网络或用 --network host。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 stress 容器模拟 CPU 压力,用 docker stats 监控 CPU 使用率变化。
  2. 进阶题(难度⭐⭐):用 docker system df -v 分析磁盘占用,执行 docker system prune -a 清理,对比清理前后的空间差异。
  3. 挑战题(难度⭐⭐⭐):用 iperf3 测试两个容器间的网络带宽,对比 bridge 网络和 host 网络的性能差异。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏