cpus是单机硬限(如'0.75'即每100ms最多运行75ms),cpu_shares是相对权重(如2048仅在CPU争抢时生效,空闲不限速);单机模式下deploy.resources完全无效,必须用顶层cpus和cpu_shares字段。

docker-compose.yml 里 cpus 和 cpu_shares 的区别必须分清
单节点 Docker Compose 场景下,deploy.resources.limits.cpus 是无效的——它只在 docker stack deploy(Swarm 模式)中生效。真正起作用的是顶层字段 cpus 和 cpu_shares,但它们机制完全不同:
-
cpus: '0.75':硬性时间片限制,等价于 cgroups 的cpu.cfs_quota_us=75000+cpu.cfs_period_us=100000,容器每 100ms 最多运行 75ms,超了就强制节流 -
cpu_shares: 2048:纯相对权重,仅在多个容器同时争抢 CPU 时才生效;空闲时不限速,也不会阻止你跑满整核
防止单节点过载,优先用 cpus;想调节服务间相对响应快慢(比如让 API 比定时任务更“抢得过 CPU”),再叠加 cpu_shares。
单机模式下 deploy.resources 完全不生效,别白配
很多人把 Swarm 的写法直接搬进 docker-compose.yml,结果发现内存照爆、CPU 照打满。这是因为 deploy 下的 resources.limits 和 resources.reservations 在 docker-compose up 中被完全忽略——Docker 引擎压根不读这些字段,也不调用 cgroups 接口。
- 错误写法:
deploy: resources: limits: cpus: '1.0' - 正确写法(单机有效):
cpus: '1.0'或mem_limit: 1G,放在 service 同级 - 环境变量可动态注入:
cpus: ${MAX_CPU},配合.env文件切换测试/生产值
OOM 杀容器前,先调低关键服务的 oom_score_adj
即使设了 mem_limit,Linux OOM Killer 仍可能误杀重要服务。默认所有容器 oom_score_adj 值接近 0,谁占内存多谁先死。你可以手动干预:
- 给核心服务(如网关、数据库代理)加:
oom_score_adj: -500,大幅降低被杀概率 - 给非关键服务(如日志收集、离线任务)加:
oom_score_adj: 300,让它当“替死鬼” - 注意:
oom_score_adj取值范围是 [-1000, 1000],-1000 表示完全免疫 OOM Killer
这个参数和 mem_limit 配合,才能形成“内存硬限 + 杀戮优先级”的双保险。
blkio_weight 是 I/O 层面的调度权重,常被漏掉
CPU 和内存争抢容易被监控到,但磁盘 I/O 争抢往往静默拖垮整个节点。比如 MySQL 和 Nginx 共享一块 SSD,没配权重时,Nginx 大量静态文件读取会卡住 MySQL 的 WAL 写入。
- MySQL 服务加:
blkio_weight: 800 - Nginx 加:
blkio_weight: 300 - 该值只在使用 CFQ 或 BFQ I/O 调度器的内核中生效,现代 Linux 默认是 BFQ,基本可用
- 注意:
blkio_weight不是硬限,只是竞争时的相对权重,不能替代device_read_bps_limit这类硬限配置
真正复杂的不是配多少,而是意识到:CPU 权重、内存 OOM 优先级、磁盘 I/O 权重,这三者要协同设置才有意义——单独调一个,其他两层照样能把你拖垮。











