Skip to content

⚙️ 资源限制

为什么要限制资源?

一个容器如果不加限制,可以吃光你所有的 CPU 和内存。想象一下:你的 MySQL 容器跑了个全表扫描,直接把宿主机的内存吃满了,结果 Nginx 也被 OOM Kill——整个服务全挂。

资源限制就是给每个容器装上"限速器",防止单个容器拖垮整台机器。

CPU 限制

bash
# --cpus:限制最多使用 1.5 个 CPU 核心
docker run -d --cpus=1.5 myapp

# --cpu-shares:按比例分配 CPU(默认 1024)
docker run -d --cpu-shares=512 light-task    # 低优先级
docker run -d --cpu-shares=2048 heavy-task   # 高优先级(4倍权重)

# --cpuset-cpus:绑定到特定 CPU 核心
docker run -d --cpuset-cpus="0,1" myapp      # 只用第 0 和 1 核

# 查看容器的 CPU 使用率
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
NAME        CPU %     MEM USAGE / LIMIT
nginx       0.50%     12.3MiB / 512MiB
mysql       45.20%    1.2GiB / 2GiB
redis       0.10%     3.8MiB / 128MiB

内存限制

bash
# 限制最多使用 512MB 内存
docker run -d --memory=512m myapp

# 同时设置软限制和硬限制(软限制超过后会触发 GC,硬限制会 OOM Kill)
docker run -d --memory=512m --memory-swap=1g myapp
# memory-swap = memory + swap,所以 swap 分配了 512m

# 禁止使用 swap(memory-swap 与 memory 相同)
docker run -d --memory=512m --memory-swap=512m myapp
# ⚠️ 不要随意加 --oom-kill-disable:内存不够时不会杀容器,可能拖垮宿主机

# 查看 OOM 事件
docker inspect --format='{{.State.OOMKilled}}' myapp
false

# 查看容器内存使用
docker stats --no-stream myapp
NAME    CPU %   MEM USAGE / LIMIT   MEM %   NET I/O       BLOCK I/O
myapp   2.30%   256MiB / 512MiB     50.00%  1.2MB / 800kB 0B / 0B

⚠️ 注意: ⚠️ 经验教训:Java 应用特别容易 OOM。给 Java 容器设 --memory 时,记得同时在应用里设 -Xmx 或使用支持容器感知的 JVM 参数,否则 JVM 可能申请超过容器限制的内存。

磁盘 IO 和重启策略

bash
# 限制磁盘写入速率(10MB/s 读,5MB/s 写)
docker run -d --device-read-bps=/dev/sda:10mb --device-write-bps=/dev/sda:5mb myapp

# 重启策略(总是、失败时、除非手动停止)
docker run -d --restart=always myapp              # 崩溃自动重启
docker run -d --restart=unless-stopped myapp      # 除非手动 stop,否则自动重启
docker run -d --restart=on-failure:5 myapp        # 最多重启 5 次

# 在 docker-compose.yml 中配置资源限制(本地 docker compose)
cat > docker-compose.yml << 'EOF'
services:
  web:
    image: nginx:alpine
    cpus: "1.0"
    mem_limit: 256m
    mem_reservation: 128m
    restart: unless-stopped

  api:
    build: ./api
    cpus: "2.0"
    mem_limit: 1g
    restart: unless-stopped
EOF

💡 提示deploy.resources 主要用于 Swarm/stack 部署;本地 docker compose up 更推荐直接使用 cpusmem_limitmem_reservation。如果你的 Compose 版本支持 deploy.resources,也要先在目标环境验证限制是否真的生效。