00:00:00
为什么需要资源限制?
在生产环境中,不对容器进行资源限制可能导致:
- 🔥 单个容器占用过多资源,影响其他容器
- 💥 内存泄漏导致宿主机 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/31.2 限制 CPU 核心数
bash
# --cpus: 限制使用的 CPU 核心数(支持小数)
docker run -d --cpus=1.5 nginx
# 限制使用 2 个 CPU 核心
docker run -d --cpus=2 redis1.3 绑定特定 CPU
bash
# --cpuset-cpus: 绑定到特定 CPU 核心
docker run -d --cpuset-cpus="0,2" nginx
# 绑定到 CPU 0-3
docker run -d --cpuset-cpus="0-3" mysql2. 内存资源限制
2.1 限制内存使用
bash
# -m 或 --memory: 限制最大内存
docker run -d -m 512m nginx
# 1GB 内存限制
docker run -d --memory=1g redis2.2 内存预留
bash
# --memory-reservation: 软限制,尽量不超过此值
docker run -d --memory=1g --memory-reservation=512m nginx2.3 禁用 OOM Killer
bash
# --oom-kill-disable: 禁用 OOM 杀死容器(需谨慎使用)
docker run -d -m 512m --oom-kill-disable nginx2.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 nginx3. 磁盘 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 nginx3.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 nginx4. 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: example5. 监控容器资源使用
5.1 实时查看
bash
# 查看所有容器资源使用
docker stats
# 查看特定容器
docker stats container_name
# 只显示一次(不持续刷新)
docker stats --no-stream5.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:latest6.2 数据库
bash
docker run -d \
--name mysql-db \
--cpus=2 \
-m 2g \
--memory-reservation=1g \
--restart=always \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.06.3 缓存服务
bash
docker run -d \
--name redis-cache \
--cpus=0.5 \
-m 256m \
--memory-reservation=128m \
--restart=always \
redis:alpine7. 注意事项
⚠️ 常见陷阱
不设置内存限制
- 容器可能耗尽宿主机内存
- 建议始终设置
-m参数
CPU 限制过严
- 可能导致应用性能严重下降
- 建议先监控再限制
忽略 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.log8. 故障排查
容器被 OOM Kill
bash
# 查看系统日志
dmesg | grep -i oom
# 查看容器日志
docker logs container_name
# 检查内存限制
docker inspect container_name | grep -i memoryCPU 节流
bash
# 检查 CPU 限制
docker inspect container_name | grep -i cpu
# 查看 CPU 使用率
docker stats container_name