Docker容器资源限制,限制CPU内存防止抢占资源
当一台服务器上跑着多个 Docker 容器时,某个容器突然吃满 CPU 或内存,会导致其他服务响应变慢甚至被系统杀掉。
解决这个问题的核心思路是:在启动容器时通过参数给它设定 CPU 和内存上限,让资源分配可控。
本文从零开始,带你用 docker run 和 docker-compose 完成限制配置,并验证限制是否真正生效。
先确认你的环境支持资源限制
Docker 的资源限制依赖 Linux 内核的 cgroups 功能。
绝大多数现代 Linux 发行版默认已启用,不需要额外安装。
你可以执行下面命令快速检查:
docker info | grep -i cgroup
如果看到 Cgroup Driver: cgroupfs 或 systemd,同时 Cgroup Version 有输出,说明环境正常。
若提示找不到 cgroup,需要先确认内核版本和启动参数,建议查阅对应发行版官方文档。
另外,运行容器的用户需要有 sudo 权限或已加入 docker 用户组。
用 docker run 限制 CPU 和内存
内存限制
使用 --memory 或简写 -m 设置容器可用内存上限,单位可以是 m(兆)或 g(吉)。
例如限制为 512MB:
docker run -d --name myapp --memory="512m" nginx:latest
如果容器内存使用超过这个值,Docker 会尝试终止容器内的进程。
你也可以额外设置 --memory-swap 控制交换分区用量:
docker run -d --name myapp --memory="512m" --memory-swap="1g" nginx:latest
这里 --memory-swap 表示内存加交换分区总共可用 1GB,实际可用交换分区为 512MB。
如果不设置 --memory-swap,默认与 --memory 相同,即不使用交换分区。
CPU 限制
CPU 限制有两种常用方式:指定核心数或指定相对权重。
指定核心数(推荐):
docker run -d --name myapp --cpus="1.5" nginx:latest
这表示容器最多使用 1.5 个 CPU 核心的算力。
指定权重(适合多个容器竞争场景):
docker run -d --name myapp --cpu-shares=512 nginx:latest
--cpu-shares 默认值是 1024,数值越大,在 CPU 资源紧张时获得的份额越多。
它不设硬上限,只影响相对分配比例。
同时限制内存和 CPU
实际使用时通常两者一起设置:
docker run -d \
--name myapp \
--memory="1g" \
--cpus="2" \
--restart=unless-stopped \
nginx:latest
执行后可以用 docker stats myapp 查看实时资源占用,确认限制是否生效。
docker-compose 中配置资源限制
如果你用 docker-compose 管理服务,
在 docker-compose.yml 中对应服务下添加 deploy.resources 或旧版 mem_limit、cpus 字段。
推荐写法(Compose V2 及以上):
services:
myapp:
image: nginx:latest
deploy:
resources:
limits:
cpus: "2"
memory: 1g
reservations:
cpus: "0.5"
memory: 256m
注意:deploy 块在非 Swarm 模式下部分字段可能被忽略,若发现限制无效,可以改用以下兼容写法:
services:
myapp:
image: nginx:latest
mem_limit: 1g
cpus: 2
修改后执行 docker-compose up -d 重建容器,再用 docker stats 检查。
容易踩坑的几个地方
- 内存限制设得太低:比如给 Java 应用只分 256MB,JVM 还没启动就被 OOM 杀掉。建议先观察容器正常运行时实际占用,再留出 30% 余量。
- 只看
--cpu-shares就以为能限制上限:它只是权重,不是硬上限。真正限制 CPU 用量要用--cpus或--cpu-quota。 - 忘记检查宿主机内核是否支持:极少数精简系统或旧内核可能未启用 cgroup 内存子系统,导致限制不生效。
- 容器内进程仍可能被系统 OOM Killer 终止:即使设置了内存限制,如果宿主机整体内存不足,内核仍可能杀掉容器进程。建议同时关注宿主机
free -h和dmesg日志。
验证限制是否真正生效
启动一个带限制的容器后,用下面两个方法交叉验证:
方法一,查看容器详细信息:
docker inspect myapp | grep -i -E "memory|cpu"
输出中能看到 Memory、NanoCpus 等字段,确认数值与设定一致。
方法二,实时监控:
docker stats myapp
MEM USAGE / LIMIT 列会显示当前用量和上限,CPU % 列会显示相对于单核的百分比。
如果上限显示为 0B 或 0%,说明限制未生效,需要回到上一步检查配置。
常见疑问
限制内存后容器启动失败,报错 Cannot allocate memory,怎么办?
先确认 --memory 值是否低于应用最小需求。
可以临时去掉限制启动一次,用 docker stats 观察峰值,再重新设定一个合理值。
--cpus 可以设成小数吗?
可以。--cpus="0.5" 表示半个核心的算力,适合低负载服务。
设置了限制,但容器还是占用了很多 CPU?
检查是否只设置了 --cpu-shares。
如果宿主机 CPU 空闲,容器仍然可以短时跑满核心,这是权重机制的正常表现。
要硬限制请用 --cpus。
docker-compose 中 deploy 不生效怎么办?
非 Swarm 模式下改用 mem_limit 和 cpus 字段,并确保 Compose 版本支持。
修改后记得 docker-compose down 再 up -d,让配置完全重建。
完成以上配置后,建议在业务低峰期做一次压力测试,观察限制值是否满足服务正常运行。
如果后续调整了应用内存需求,同步更新启动参数或 compose 文件即可。