容器资源配额限制防止进程抢占内存

为什么容器内存需要配额限制?

在多人共用服务器或运行多个容器时,
如果某个容器内的进程因为程序Bug(如内存泄漏)或突发流量持续占用内存,
可能直接拖垮宿主机的内存资源,
导致其他服务被系统OOM Killer杀掉甚至整机无响应。给容器设定内存配额限制是防止这种“一颗老鼠屎坏一锅汤”最直接的手段。

本文以Docker为例,从零开始教你设置内存上限、限制swap使用、以及验证限制是否生效。
不管你是刚接触容器的新手,还是想巩固基础的老手,都可以照着做。

前提准备:安装Docker并创建一个测试容器

操作前需要一台Linux服务器(CentOS 7+ 或 Ubuntu 18.04+),并确保Docker已安装。
如果还没装,执行下面命令(Ubuntu为例):

sudo apt update
sudo apt install docker.io -y
sudo systemctl start docker
sudo systemctl enable docker

接着拉取一个轻量级压力测试镜像(用于验证内存限制):

docker pull polinux/stress

这个镜像是常用的CPU/内存压力测试工具,请放心使用,它不会对主机造成持久影响。

第一步:通过 docker run 直接设置内存上限

最简单的方式是在启动容器时使用 --memory 参数。
例如,限制容器最多使用512MB内存,并且一旦超过就会触发OOM Kill:

docker run -it --memory=512m polinux/stress --vm 1 --vm-bytes 500m --vm-hang 1
  • --memory=512m:容器内存硬限制,不允许超过512MB。
  • --vm 1:启用一个内存压力线程。
  • --vm-bytes 500m:每个线程分配500MB内存(故意接近限制,但不超过)。
  • --vm-hang 1:分配后挂起1秒再释放,模拟持久占用。

如果容器进程试图申请超过512MB内存(比如把 --vm-bytes 改成600m),容器会立即被Kill,终端输出类似 Killedexit code 137

重点--memory 是硬限制,同时建议配合 --memory-swap 控制swap使用。
默认情况下,Docker允许容器使用与 --memory 等量的swap空间。
如果不想使用swap,添加 --memory-swap=512m(与内存大小相同)。

第二步:使用 Docker Compose 统一管理内存限制

在实际项目中使用 docker-compose.yml 文件更方便。
services 下对应的容器中添加 deploy.resources 字段:

version: '3.8'
services:
  web:
    image: nginx:latest
    deploy:
      resources:
        limits:
          memory: 256M
        reservations:
          memory: 128M
  • limits.memory:硬上限,超限则被Kill。
  • reservations.memory:软预留,告诉调度器至少保留这么多内存(Swarm模式下生效,单机使用不影响,但可作为配置规范)。

单机docker-compose启动时需加上 --compatibility 标志才能识别 deploy 字段:

docker-compose --compatibility up -d

如果你使用的是更现代的 docker compose(v2),默认支持该语法,无需额外参数。

第三步:对运行中的容器动态调整内存限制

某些场景下容器已经启动,发现内存占用过高,此时可以用 docker update 实时修改内存限制:

docker update --memory=384m <容器名或ID>

例如对一个名为 my_app 的容器:

docker update --memory=384m my_app

修改后立即生效,可以通过 docker stats 查看当前限制是否变为384MiB。

避坑指南:几个容易踩的误区

  1. 内存限制不等于内存预留--memory 是上限,并不保证容器一定能拿到这么多内存。如果宿主机内存不足,容器可能被OOM Killer优先杀掉。需要同时设置 --memory-reservation 作为软下限(在 docker rundocker-compose 中均可设置)。
  2. swap 限制容易被忽略:默认情况下,容器可以使用与物理内存等量的swap。若你的系统swap空间很大,容器通过swap仍可占用大量磁盘IO,影响整体性能。建议明确设置 --memory-swap,例如 --memory=512m --memory-swap=512m 表示禁止使用swap。
  3. OOM优先级调整:如果希望某个重要容器即使内存超限也不被优先杀掉,可以添加 --oom-kill-disable=true 参数。但要注意:该参数只能与 --memory 同时使用,否则无效。使用后容器会进入“卡死”状态而不是被Kill,需要谨慎。

效果验证:如何确认限制已生效

方法一:使用 docker stats 实时查看

docker stats

输出会显示每个容器的CPU%、MEM USAGE / LIMIT、MEM%。
如果LIMIT列显示你设置的值(如512MiB),说明限制已生效。

方法二:压力测试触发OOM

启动一个需要超过限制内存的容器:

docker run -it --memory=256m polinux/stress --vm 1 --vm-bytes 300m

容器会立即退出,终端输出类似:

Killed

通过 docker ps -a 可以看到该容器状态为 Exited (137),137表示被SIGKILL信号结束。

方法三:在容器内查看 cgroup 限制

进入容器后执行:

cat /sys/fs/cgroup/memory/memory.limit_in_bytes

输出的数值(如 536870912)等于 512MB。
如果该值等于你设置的值,说明内核层面确实已经限制。

常见问题解答

Q:为什么我设置了内存限制,容器还是占用了超过限制的内存?
A:检查是否设置了swap。如果没有指定 --memory-swap,Docker默认允许容器使用等量swap,所以实际可用的内存+swap可能为两倍。请设置 --memory-swap--memory 相等。

Q:内存限制设置后,容器内的进程是否会感知到?
A:不会。容器内进程仍然认为系统有全部可用内存,但因为cgroup的限制,当它尝试申请超过配额内存时会被内核阻止并收到OOM。所以不要依赖应用自己控制内存,需要外部限制。

Q:能否限制单个容器内的多个进程使用内存?
A:可以。如果你在容器内运行多进程(例如supervisor管理多个服务),设置的内存限制是容器整体上限,所有进程共享。要细分请考虑使用更细粒度的cgroup或者每个进程单独容器化。

总结

通过给容器设置内存配额限制,可以避免单个进程的异常内存占用拖垮整台服务器。
核心操作就三步:启动时用 --memory、编写 docker-compose.yml 时用 deploy.resources.limits.memory、运行时用 docker update 实时调整。
不要忘记检查swap设置,并在生产环境中结合 --memory-reservation 确保关键服务的资源保障。

如果你正在处理容器资源配额防止进程抢占内存的问题,建议先按本文步骤先在测试环境跑通,再应用到生产。
遇到限制不生效或容器异常退出时,优先查看 docker logsdocker inspect 确认资源配置是否正确。

分享到:
上一篇
跨域API请求Nginx配置修复外贸站点
下一篇
Linux系统时间同步chrony配置校准实操教程
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意