--cpuset-cpus是硬性绑定容器到指定物理cpu核心的参数,支持"0,2"或"2-5"格式,内核调度器禁止进程在列表外核心运行;需配合lscpu确认拓扑,启动后通过cat /proc/self/status | grep cpus_allowed_list验证。

容器只能跑在特定 CPU 核心上:用 --cpuset-cpus
想让容器不“乱跳”、固定绑定到某些物理核心(比如只用 CPU0 和 CPU2),必须用 --cpuset-cpus。它和 --cpus 完全不同:--cpus 是软性时间配额,而 --cpuset-cpus 是硬性亲和性绑定——内核调度器不会把进程调度到未指定的核心上。
常见错误是以为 --cpus="1" 就等于绑定了某个核,其实它只是限制总使用量为 1 核,可能跨所有可用核动态调度。
-
--cpuset-cpus="0":只在第 0 号逻辑 CPU 上运行(注意:超线程下 CPU0 和 CPU1 可能是同一物理核的两个逻辑核) -
--cpuset-cpus="0-3":允许使用编号 0、1、2、3 的逻辑 CPU -
--cpuset-cpus="0,2":只允许在逻辑 CPU 0 和 2 上运行(常用于隔离干扰,比如避开被监控进程占用的核心) - 在
docker-compose.yml中要写成:deploy:<br> resources:<br> reservations:<br> cpus: "1"<br> limits:<br> cpus: "1"<br> placement:<br> constraints:<br> - node.labels.cpu02 == true
但注意:--cpuset-cpus不支持直接写在deploy.resources下,得用command或提前配置 Docker daemon 的default-runtime,更实际的做法是改用docker run启动时显式传参
Docker Desktop 本身占太多 CPU?先调虚拟机资源上限
Docker Desktop 在 macOS/Windows 上本质是个 Linux 虚拟机(Hyper-V 或 HyperKit),容器的 CPU 最终都从这个 VM 里分。如果你发现宿主机风扇狂转、Activity Monitor 显示 “Docker Desktop” 进程吃满 CPU,大概率不是某个容器的问题,而是 VM 自身没设限。
必须进 Docker Desktop 设置里调全局资源,否则 --cpuset-cpus 再准也没用——VM 层已经把整机 CPU 拿走了。
- macOS:点击菜单栏
? → Settings → Resources → Advanced,重点调CPUs(建议 ≤ 物理核数 × 0.75)和Memory(建议 ≤ 总内存 × 0.5) - Windows(WSL2 后端):同样路径,但部分旧版 WSL2 需额外编辑
%USERPROFILE%\AppData\Local\Docker\wsl\data\wsl.conf加processors=2才生效 - 改完必须点
Apply & Restart,不重启无效
--cpus 和 --cpuset-cpus 能一起用吗?可以,但目的不同
能一起用,而且经常需要组合:前者控“总量”,后者控“位置”。比如你有 8 核 CPU,想让数据库容器最多用 2 核、且只跑在后 4 核上避免干扰前台应用,命令就是:
docker run -d --cpus="2" --cpuset-cpus="4-7" postgres
这里 --cpus="2" 是 CFS 时间片上限(软限),--cpuset-cpus="4-7" 是调度器亲和性(硬限)。两者不冲突,但要注意:
- 如果
--cpuset-cpus指定的核数少于--cpus值(如--cpuset-cpus="0"+--cpus="2"),容器仍只能用 1 核——因为绑死单核后,再高的配额也调度不出去 -
--cpu-shares是相对权重,只在多个容器争抢时起作用;单独一个容器跑满也不会受它约束 - 在 macOS 上,
--cpuset-cpus实际生效依赖于底层 VM 的 CPU topology 暴露程度,有时会看到docker stats显示 usage 均匀分布在多个核上——那说明 VM 层做了负载均衡,此时绑定效果打折扣
验证容器真绑在指定核心上了?别信 docker stats
docker stats 显示的是整体 CPU 使用率百分比,完全看不出绑定情况。真正要看是否生效,得进容器里查 /proc/self/status 或宿主机上查 cgroup:
- 进容器执行:
cat /proc/self/status | grep Cpus_allowed_list
返回值如0,2表示确实只被允许在 CPU0 和 CPU2 上运行 - 在宿主机查(需知道容器 ID):
cat /sys/fs/cgroup/cpuset/docker//cpuset.cpus
结果应与你传入的--cpuset-cpus一致 - 用
htop并开启“树状视图”(F5)和“显示 CPU 核心”(F2 → Display options → Show custom thread names),观察进程是否只出现在你指定的列里
最容易忽略的一点:Docker Desktop 的 macOS 版本对 --cpuset-cpus 支持不稳定,尤其在 Apple Silicon(M1/M2/M3)上,部分内核版本会静默忽略该参数——这时得切回 Intel 版 Docker Desktop 或改用 lima + nerdctl 组合才可靠。











