容器资源配额限制防止进程耗尽内存CPU:容器资源配额限制
如果你的服务器上跑着多个容器,
某个容器里的进程突然把内存吃光或CPU跑满,
其他容器甚至宿主机都可能跟着遭殃。容器资源配额限制就是解决这个问题的标准手段——给每个容器划定内存和CPU的上限,
超出就直接杀掉进程或限流,
确保业务互不干扰。
本文全程操作基于Docker,适合刚接触容器的小伙伴。
读完你就能自己配好限制,并且知道怎么验证是否生效。
开始前的环境检查
需要一台安装了Docker的Linux服务器。
你可以用下面命令确认版本,Docker 19.03以上对资源限制的支持更完整:
docker --version
同时确认内核开启了cgroup(默认一般都有),运行以下命令看到cgroup相关目录就说明正常:
ls /sys/fs/cgroup/memory/
用 docker run 和 docker-compose 设置资源限制
使用 docker run 命令行
启动容器时通过 -m 或 --memory 限制内存,--cpus 限制CPU核心数。
例如限制最多使用200MB内存和0.5个CPU核心:
docker run -d --name myapp -m 200m --cpus 0.5 nginx:alpine
-m 后面的 m 表示兆字节,也可以用 g 表示千兆。--cpus 填小数或整数,0.5代表半个物理核心。
如果还希望严格控制内存+swap的总和,可以加上 --memory-swap 参数。
比如限制内存200MB,swap最多再加100MB:
docker run -d --name myapp -m 200m --memory-swap 300m nginx:alpine
注意:--memory-swap 要大于 --memory,差值就是可用的swap大小。
如果不想用swap,可以设成和 --memory 一样的值。
使用 docker-compose(适合多容器场景)
在 docker-compose.yml 的 service 下添加 deploy 字段(Swarm模式)或 mem_limit/cpus 字段(普通Compose)。
推荐用 deploy 写法,兼容性更好:
version: '3.8'
services:
web:
image: nginx:alpine
deploy:
resources:
limits:
cpus: '0.5'
memory: 200M
注意 memory 后面用 M(大写)。
如果使用 mem_limit 和 cpus 字段,写法如下:
services:
web:
image: nginx:alpine
mem_limit: 200m
cpus: 0.5
建议统一用 deploy 方式,既能在单机Compose用,也能直接上Swarm。
常见配置错误与解决方案
错误1:只限制内存,没限制swap
很多教程只写 -m 200m,
但宿主机swap很大的情况下,
进程实际可用内存是(200MB + swap),
可能远超预期。解决方法: 同时设置 --memory-swap,
数值和 --memory 一样即可禁止swap。
错误2:CPU限制未生效
--cpus 只在宿主机CPU压力大时才严格限流。
如果你只运行一个容器,它依然可以跑满单个核心。
想硬限制固定时间片的CPU使用率,可以考虑使用 --cpu-period 和 --cpu-quota,但日常场景用 --cpus 足够。
错误3:docker-compose 中语法不统一
Compose v3 中 mem_limit 和 mem_reservation 已弃用,推荐用 deploy.resources.limits。
如果使用旧写法,Docker会报警告。
用 stress 工具验证限制是否生效
启动一个测试容器,安装 stress 工具,然后故意吃内存或CPU,观察是否被限制。
拉取 Ubuntu 镜像:
docker run -it --rm --name test-stress -m 200m ubuntu bash
在容器内安装 stress:
apt update && apt install -y stress
先测试内存:
stress --vm-bytes 300m --vm 1 --timeout 20s
此时因为分配300MB超过了200MB限制,你应该看到进程被OOM杀死,容器自动退出。
用 docker stats 可以实时观察当前容器的内存占用峰值:
docker stats test-stress
再测试CPU,执行:
stress --cpu 2 --timeout 10s
由于 --cpus 限制为0.5(这里我们没设,默认无限制),如果你设置了0.5,则CPU占用会被控制在50%左右(单核)。
高频问题解答
Q:已经运行的容器还能改资源限制吗?
A:可以。使用 docker update 命令,例如:
docker update --memory 300m --cpus 0.8 myapp
修改后立即生效,无需重启容器。
Q:限制内存后容器进程被OOM杀掉怎么办?
A:这是预期行为。如果不想被杀死,可以设置 --memory-reservation 软限制(配合 --memory),但不推荐。建议先排查进程内存泄漏问题,或者适当提高限制值。
Q:Kubernetes里的资源限制和Docker一样吗?
A:底层原理相同,K8s通过 requests 和 limits 字段控制,最终也是由cgroup实现。但配置方式不同,本文只针对纯Docker场景。
如果你正在处理容器资源配额限制,建议先按本文步骤完整执行一次,再根据实际业务的内存和CPU消耗微调参数。
遇到容器被OOM或者性能问题时,优先回看“常见配置错误”部分,多数情况都是swap或参数遗漏导致的。