只设 -m 会默认启用 swap,导致宿主机变慢;应同时指定 --memory-swap 与 -m 相等来彻底禁用 swap,避免换页和 OOM 延迟。

只设 -m 会悄悄启用 swap,宿主机可能被拖慢
很多人用 docker run -m 512m 启动容器后,发现 top 或 docker stats 显示内存用了 900MB+,以为限制失效了。其实不是 bug——Docker Desktop(和所有 Docker 引擎)默认把 --memory-swap 设为 -m 的两倍。也就是说,-m 512m 实际等价于 --memory-swap 1g,容器能用 512MB 物理内存 + 最多 512MB swap。一旦物理内存耗尽,内核就开始疯狂换页,宿主机响应变卡,其他容器也受影响。
--memory-swap=0 在 Docker Desktop 上多数不可用
Docker Desktop 底层用的是 LinuxKit 或 WSL2,而多数内核版本不支持 --memory-swap=0 这个组合(报错 invalid argument: memory-swap must be greater than or equal to memory)。真正可靠、跨平台生效的做法是让两个值相等:
docker run -m 512m --memory-swap 512m nginxdocker run -m 2g --memory-swap 2g my-java-app
这时 memory.memsw.limit_in_bytes 和 memory.limit_in_bytes 数值一致,swap 被彻底禁用,超限直接 OOM Kill,不换页、不卡宿主机。
Docker Compose 中必须显式写全,不能只靠 mem_limit
Docker Compose 的 mem_limit 字段只对应 -m,它**不会自动同步设置 --memory-swap**。如果你只写:
services:
app:
image: alpine
mem_limit: 512m
那实际还是默认启用 swap。正确写法是用 deploy.resources.limits 并补全 memory_swap(注意:这个字段名是 memory_swap,不是 mem_swap 或 swap):
services:
app:
image: alpine
deploy:
resources:
limits:
memory: 512m
memory_swap: 512m
否则 docker-compose up 启动后,docker inspect 里仍能看到 MemorySwap 是 -1 或 1073741824(即 1GB),说明 swap 没关掉。
验证是否真禁用了 swap,别信 docker stats
docker stats 只显示当前使用量,不反映 swap 是否启用。真正可靠的验证方式只有两个:
- 进容器执行:
cat /sys/fs/cgroup/memory/memory.limit_in_bytes和cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes—— 两者数值必须完全相等 - 在宿主机上查:
docker inspect container-name | grep -E "(Memory|MemorySwap)",确认Memory和MemorySwap字段值相同且不为-1
如果看到 MemorySwap 是 -1 或明显大于 Memory,说明 swap 还开着,哪怕容器当前没用到,风险仍在。


















