Skip to content
0

文章发布较早,内容可能过时,阅读注意甄别。

为什么需要资源限制?

在生产环境中,不对容器进行资源限制可能导致:

  • 🔥 单个容器占用过多资源,影响其他容器
  • 💥 内存泄漏导致宿主机 OOM
  • 📉 性能不稳定,难以预测

1. CPU 资源限制

1.1 限制 CPU 份额(相对权重)

bash
# --cpu-shares: 默认值 1024,相对权重
docker run -d --cpu-shares=512 nginx

# 示例:容器 A(1024)和容器 B(512)
# 在 CPU 繁忙时,A 获得 2/3 资源,B 获得 1/3

1.2 限制 CPU 核心数

bash
# --cpus: 限制使用的 CPU 核心数(支持小数)
docker run -d --cpus=1.5 nginx

# 限制使用 2 个 CPU 核心
docker run -d --cpus=2 redis

1.3 绑定特定 CPU

bash
# --cpuset-cpus: 绑定到特定 CPU 核心
docker run -d --cpuset-cpus="0,2" nginx

# 绑定到 CPU 0-3
docker run -d --cpuset-cpus="0-3" mysql

2. 内存资源限制

2.1 限制内存使用

bash
# -m 或 --memory: 限制最大内存
docker run -d -m 512m nginx

# 1GB 内存限制
docker run -d --memory=1g redis

2.2 内存预留

bash
# --memory-reservation: 软限制,尽量不超过此值
docker run -d --memory=1g --memory-reservation=512m nginx

2.3 禁用 OOM Killer

bash
# --oom-kill-disable: 禁用 OOM 杀死容器(需谨慎使用)
docker run -d -m 512m --oom-kill-disable nginx

2.4 Swap 限制

bash
# --memory-swap: 内存 + Swap 总量
# 设置为 -1 表示无限制
docker run -d -m 512m --memory-swap=1g nginx

# 禁用 Swap
docker run -d -m 512m --memory-swap=512m nginx

3. 磁盘 I/O 限制

3.1 限制读写速率

bash
# --device-read-bps: 限制读取速率
docker run -d --device-read-bps=/dev/sda:10mb nginx

# --device-write-bps: 限制写入速率
docker run -d --device-write-bps=/dev/sda:10mb nginx

3.2 限制 IOPS

bash
# --device-read-iops: 限制每秒读取次数
docker run -d --device-read-iops=/dev/sda:1000 nginx

# --device-write-iops: 限制每秒写入次数
docker run -d --device-write-iops=/dev/sda:1000 nginx

4. Docker Compose 配置示例

yaml
version: '3.8'

services:
  web:
    image: nginx:latest
    deploy:
      resources:
        limits:
          cpus: '1.5'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

  db:
    image: mysql:8.0
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G
    environment:
      MYSQL_ROOT_PASSWORD: example

5. 监控容器资源使用

5.1 实时查看

bash
# 查看所有容器资源使用
docker stats

# 查看特定容器
docker stats container_name

# 只显示一次(不持续刷新)
docker stats --no-stream

5.2 查看容器配置

bash
# 查看容器详细信息
docker inspect container_name | grep -A 10 "Memory"

# 使用 jq 格式化输出
docker inspect container_name | jq '.[0].HostConfig | {Memory, CpuShares, CpuQuota}'

6. 生产环境推荐配置

6.1 Web 应用

bash
docker run -d \
  --name web-app \
  --cpus=1 \
  -m 512m \
  --memory-reservation=256m \
  --restart=always \
  nginx:latest

6.2 数据库

bash
docker run -d \
  --name mysql-db \
  --cpus=2 \
  -m 2g \
  --memory-reservation=1g \
  --restart=always \
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8.0

6.3 缓存服务

bash
docker run -d \
  --name redis-cache \
  --cpus=0.5 \
  -m 256m \
  --memory-reservation=128m \
  --restart=always \
  redis:alpine

7. 注意事项

⚠️ 常见陷阱

  1. 不设置内存限制

    • 容器可能耗尽宿主机内存
    • 建议始终设置 -m 参数
  2. CPU 限制过严

    • 可能导致应用性能严重下降
    • 建议先监控再限制
  3. 忽略 Swap 配置

    • 默认情况下 Swap = Memory * 2
    • 数据库等场景建议禁用 Swap

💡 最佳实践

bash
# 1. 先运行不限制资源,监控实际使用量
docker stats container_name

# 2. 根据峰值设置限制(留 20-30% 余量)
# 如果峰值 700MB,设置为 1GB

# 3. 设置软限制(reservation)为平均值
# 如果平均 400MB,设置 reservation=400m

# 4. 定期检查和调整
docker stats --no-stream > stats.log

8. 故障排查

容器被 OOM Kill

bash
# 查看系统日志
dmesg | grep -i oom

# 查看容器日志
docker logs container_name

# 检查内存限制
docker inspect container_name | grep -i memory

CPU 节流

bash
# 检查 CPU 限制
docker inspect container_name | grep -i cpu

# 查看 CPU 使用率
docker stats container_name

参考资料

最近更新