必须同步设置 -m 和 --memory-swap 才能真正限制物理内存上限;仅设 -m 512m 时 Docker 默认启用等量 swap(--memory-swap=1g),实际可用内存达 1GB 且 OOM 不可控;禁用 swap 需显式指定 --memory-swap=512m。

限制单个容器最大内存,关键不是只写 -m,而是必须同步控制 swap 行为,否则实际可用内存会翻倍,OOM 时机不可控。
用 -m 和 --memory-swap 组合设硬上限
只设 -m 512m 不够——Docker 默认将 --memory-swap 设为 1g(即物理内存 + 等量 swap),容器最多能用到 1GB 才被杀。要真正卡死在 512MB 物理内存,必须显式指定:
-
docker run -m 512m --memory-swap=512m nginx:禁用 swap,超 512MB 直接触发 OOM Killer -
--memory-swap值不能小于-m,否则启动失败 - 值为
-1表示不限 swap,生产环境严禁
验证底层 cgroup 是否真实生效
docker inspect 只显示启动参数,不反映运行时状态。必须查 sysfs:
- 获取容器 PID:
docker inspect -f '{{.State.Pid}}' 容器名 - 定位 cgroup 路径:
cat /proc/$PID/cgroup,找类似0::/docker/abc123的行 - 检查限制值:
cat /sys/fs/cgroup/docker/abc123/memory.max应为536870912(512MB 字节数) - 同时确认:
cat /sys/fs/cgroup/docker/abc123/memory.swap.max必须与前者相等,表示 swap 已关闭
确保宿主机启用 cgroups v2
cgroups v1 多挂载点、行为不一致,容易漏控;v2 是统一单层级,生产唯一推荐:
- 运行
mount | grep cgroup2,看到cgroup2 on /sys/fs/cgroup type cgroup2才正常 - 检查
/sys/fs/cgroup/cgroup.controllers是否存在且非空(v1 下该路径不存在) - 若未启用:编辑
/etc/default/grub,追加cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1,再执行sudo update-grub && sudo reboot
配合应用层做协同限制
容器限制只是第一道防线,Java、Node.js 等运行时可能自行申请堆外内存或缓存,绕过 cgroup:
- JVM 需同步设
-Xmx384m(建议为-m值的 75%),避免堆外内存撑爆限额 - 监控
container_memory_usage_bytes指标,持续超限 85% 达 90 秒即告警 - 避免使用
--oom-kill-disable,它会让内核不杀进程而杀子进程,行为更难预测


















