在默认配置下,Docker 容器没有明确的 CPU 和内存上限,可以使用宿主机调度器允许的资源。如果某个容器出现死循环、突发流量或内存泄漏,就可能挤占其他服务的运行空间,严重时甚至触发宿主机 OOM。合理设置资源配额,能够提高服务稳定性、增强资源隔离,并让容量规划更有依据。🛡️
一、配置前先了解资源限制机制
Docker 的资源管理依赖 Linux 内核的控制组机制。CPU 限制主要控制容器获得的处理器时间或可使用的核心,内存限制则用于设置可用内存、交换空间和软限制。实际使用前,可执行 docker info 检查宿主机能力;如果输出中出现 No swap limit support 等警告,应先检查内核与控制组配置。详细参数可参考 Docker 官方资源限制文档。
二、设置容器 CPU 配额
1. 使用 --cpus 限制 CPU 总量
--cpus 是最直观的 CPU 配额参数。例如:
docker run -d --name web --cpus=1.5 nginx
这表示容器最多可以获得相当于 1.5 个 CPU 核心的计算时间。它不要求容器始终运行在某几个固定核心上,而是由调度器在允许的 CPU 范围内分配时间。
2. 使用 --cpu-period 和 --cpu-quota 精细控制
需要更细粒度控制时,可以组合使用 --cpu-period 与 --cpu-quota。例如:
docker run -d --cpu-period=100000 --cpu-quota=50000 nginx
该配置表示在每个 100000 微秒的调度周期内,容器最多使用 50000 微秒 CPU 时间,效果相当于 0.5 个 CPU。通常优先使用更易读的 --cpus,只有在兼容旧脚本或需要精确配置时再使用这组参数。
3. 通过 --cpuset-cpus 绑定核心
如果希望容器只在指定核心上运行,可以使用:
docker run -d --cpuset-cpus="0,2" nginx
此时容器只能在编号为 0 和 2 的逻辑 CPU 上调度。绑定核心适合对缓存命中率、延迟抖动或资源隔离有明确要求的场景,但配置不当也可能造成部分核心繁忙、其他核心空闲。⚙️
4. 使用 --cpu-shares 设置竞争权重
--cpu-shares 设置的是相对权重,而不是绝对上限。只有多个容器同时争抢 CPU 时,权重差异才会产生明显作用。例如一个容器设置为 1024,另一个设置为 512,在资源竞争时,前者通常可以获得更高的调度权重。若宿主机 CPU 空闲,设置较低权重的容器仍可能使用更多 CPU。
三、配置容器内存限制
1. 设置内存硬上限
使用 --memory 或简写 -m 可以设置容器内存上限:
docker run -d --name api --memory=512m nginx
当容器内进程持续申请内存并超过限制时,可能触发 OOM,相关进程可能被内核终止。因此,内存限制不应凭经验随意填写,建议先通过压测和监控获得应用的稳定使用量、峰值与增长趋势。
2. 正确理解 --memory-swap
--memory-swap 表示容器可使用的内存与交换空间总量,并且只有配合 --memory 才有意义。例如:
docker run -d --memory=512m --memory-swap=1g nginx
该容器最多可使用 512MB 内存,并可额外使用一定的交换空间,总量不超过 1GB。如果将 --memory-swap 设置为与 --memory 相同的值,则容器无法使用交换空间。交换空间速度通常低于物理内存,延迟敏感型应用应谨慎启用。
3. 添加内存软限制
--memory-reservation 可以设置低于硬上限的软限制,例如:
docker run -d --memory=1g --memory-reservation=768m nginx
当宿主机出现资源竞争或内存紧张时,系统会尝试让容器按照软限制运行,但软限制不能保证容器绝对不超过该值。因此,它适合作为弹性管理手段,不能替代 --memory 硬限制。
四、组合配置与动态调整
一个常见的组合示例如下:
docker run -d --name app --cpus=1.5 --memory=768m --memory-reservation=512m --memory-swap=1g nginx
这套配置同时限定 CPU、物理内存和内存加交换空间总量。对于已经运行的容器,可使用:
docker update --cpus=2 --memory=1g --memory-swap=1536m app
动态修改后仍应观察应用是否发生延迟升高、频繁垃圾回收或 OOM,避免只关注配置是否成功。
五、监控与验证资源配额
执行 docker stats 可以实时查看容器的 CPU 使用率、内存用量、内存限制、网络流量和块设备 I/O。使用 docker inspect 容器名 则可以核对容器实际生效的 HostConfig 配置。若容器意外退出,可结合以下信息排查:
- 通过 docker inspect 容器名 查看 OOMKilled 状态。
- 通过 docker logs 容器名 检查应用日志。
- 通过宿主机系统日志确认是否发生内存不足或控制组异常。
- 持续记录峰值数据,不要仅根据某一时刻的平均使用率调整配额。
六、生产环境配置建议
- 先压测后定额,为正常峰值和短时突发保留合理余量。📊
- 同时配置 CPU 与内存,避免只限制单一资源形成新的瓶颈。
- 核心服务优先使用硬限制配合持续监控,批处理任务可设置较低 CPU 权重。
- 不要轻易关闭 OOM 保护,否则容器失控时可能影响宿主机上的其他进程。
- 修改配额后进行回归测试,重点观察响应时间、错误率和重启次数。
资源限制不是数值越小越好。过于宽松无法形成隔离,过于严格则会导致性能下降、请求超时或容器频繁退出。正确做法是以真实负载数据为基础,持续监控并逐步调整。
总结
Docker 提供了 --cpus、--cpuset-cpus、--cpu-shares、--memory、--memory-swap 和 --memory-reservation 等参数,可分别实现 CPU 配额、核心绑定、竞争权重以及内存软硬限制。生产环境中应把资源限制、压力测试、运行监控和异常排查结合起来,建立可复用的配置基线,才能在提高宿主机利用率的同时,避免单个容器影响整套服务。✅