docker容器cpu和内存限制需用--cpus和--memory参数,值带单位(如--cpus=1.5、--memory=512m),并配--memory-swap;docker-compose中对应cpus和mem_limit字段,数值不加引号,建议同时设mem_reservation作为软限制;--cpus不生效多因cgroups v1或docker驱动未启用systemd,需验证/sys/fs/cgroup/cpu.max及daemon配置;容器内cpu核心数仍显示宿主机总数属正常,实际限制通过throttling指标体现。

docker run 里怎么设 CPU 和内存上限
直接用 --cpus 和 --memory 就行,这是最常用也最稳妥的方式。不加限制时容器能吃光宿主机资源,尤其在多容器共存的机器上,一个失控的容器可能拖垮整个服务。
常见错误是写成 --cpu=2(错)或 --mem=1g(错),正确参数名只有 --cpus 和 --memory,且值要带单位:
-
--cpus=1.5:限制最多用 1.5 个逻辑 CPU(支持小数) -
--memory=512m或--memory=2g:注意必须带m或g,写512会被当字节,等于几乎没限 - 内存必须同时配
--memory-swap=512m(否则默认不限制 swap,实际还是可能爆)
docker-compose.yml 中对应怎么写
YAML 里字段名和 CLI 一致,但要注意缩进和类型——数值写成字符串反而会报错。
典型错误是把 mem_limit: 512m 写成 mem_limit: "512m"(引号导致解析失败),或者漏掉 mem_reservation 导致 OOM 被杀前没预警。
- CPU:
cpus: 2.0(浮点数,不是字符串) - 内存:
mem_limit: 1024m+mem_reservation: 512m(后者是软限制,建议设为上限的 60%~80%) - 别写
memswap_limit,新版推荐用mem_swappiness: 0控制 swap 倾向
为什么 --cpus 有时不生效
根本原因是宿主机内核没开 cgroups v2,或者 Docker daemon 启动时没启用 systemd 驱动。CentOS 7 / Ubuntu 18.04 默认用 cgroups v1,--cpus 实际走的是 --cpu-period + --cpu-quota 模拟,容易受其他进程干扰。
验证方式:进容器跑 cat /sys/fs/cgroup/cpu.max,如果返回 max max,说明限制根本没落下去。
- 检查宿主机:
stat -fc %T /sys/fs/cgroup,输出cgroup2fs才是 v2 - Docker daemon 配置里确认
"exec-opts": ["native.cgroupdriver=systemd"] - Ubuntu 22.04+ 默认 ok;CentOS 7 建议升级或手动切驱动
容器里看到的 CPU 核心数还是宿主机的总数
这是正常现象。--cpus 限制的是使用率,不是“可见核心数”。容器里 nproc 或 lscpu 显示的仍是宿主机的 CPU 列表,但超过限额的部分会被内核 throttle,表现为高负载下进程卡顿、调度延迟上升。
真正反映限制是否起作用的指标是:docker stats <container></container> 里的 CPUs 和 %MEM 列,以及 /sys/fs/cgroup/cpu.stat 中的 nr_throttled(非零说明已被限频)。
- 别依赖
cat /proc/cpuinfo | grep processor | wc -l判断 CPU 可用量 - 压测时关注
throttling_periods,持续增长说明限额太紧 - Java 应用需额外传
-XX:+UseContainerSupport,否则 JVM 仍按宿主机 CPU 数算线程池大小










