linux 容器资源限制依赖 cgroups 内核机制,内存限制防 oom 杀进程,cpu 限制分配时间片而非绑定核心,io 限速需按真实设备路径配置,pid 限制防 fork 炸弹。

Linux 容器的资源限制核心靠 cgroups 实现,不是靠 Docker 或 Podman 本身“限制”,而是它们调用内核接口配置 cgroups。真正起作用的是内核对 CPU、内存、IO 等子系统的控制能力。
内存限制:避免 OOM 杀进程
容器内存超限时,内核 OOM Killer 可能直接杀死容器内主进程(如 PID 1)。设置 –memory(如–memory=512m)会限制 cgroup v1 的memory.limit_in_bytes,或 cgroup v2 的memory.max。建议同时配–memory-swap=512m 禁用 swap,防止内存压力转移到磁盘;若允许 swap,设为–memory-swap=1g(即内存 +swap 总和)。
- 查看实际限制:进入容器后读/sys/fs/cgroup/memory.max(cgroup v2)或/sys/fs/cgroup/memory/memory.limit_in_bytes(v1)
- 监控使用量:查 /sys/fs/cgroup/memory.current,比docker stats 更底层、无延迟
- 注意软限制无效:–memory-reservation仅作提示,不强制生效,不能替代硬限制
CPU 限制:控制时间片而非核心数
CPU 限制本质是分配 CPU 时间比例,不是绑定物理核心(那是 –cpuset-cpus 干的事)。常用两种方式:
- –cpus=1.5:在 cgroup v2 下设cpu.max = 150000 100000(表示每 100ms 最多用 150ms CPU 时间),适合突发负载场景
- –cpu-quota=15000 –cpu-period=10000:等价于 1.5 核,但需手动配周期,v1/v2 均支持
- 避免只设–cpu-shares:它只在 CPU 争抢时起相对权重作用,空闲时不生效,不适合做硬约束
IO 限速:按设备路径精细控制
Docker 默认不限 IO,需显式配置。关键点在于设备路径必须真实存在且被容器挂载:
- –device-read-bps=/dev/sda:1mb:限制读吞吐为 1MB/s,适用于数据库容器防 IO 打满
- –device-write-iops=/dev/sdb:50:限制写 IOPS 为 50 次 / 秒,适合日志密集型服务
- 注意:宿主机 /dev/sda 在容器里可能变成 /dev/nvme0n1,需先用 lsblk 确认实际设备名再配置
- cgroup v2 下 IO 策略更统一,推荐启用 systemd.unified_cgroup_hierarchy=1 启动参数
PID 与进程数限制:防 fork 炸弹
默认容器 PID 数无上限,一个恶意进程反复 fork 可耗尽宿主机 pid_max。通过 –pids-limit 可硬限制:
- –pids-limit=100对应 cgroup v2 的pids.max,超过则 fork 失败并返回 EAGAIN
- Java 应用注意:JVM 线程数 + GC 线程 + 应用线程总和不能超此值,否则启动报java.lang.OutOfMemoryError: unable to create native thread
- 配合 –ulimit nproc=50 双重防护,限制单用户进程数(影响 shell 内启动的子进程)






























