别让一个容器吃掉整台 VPS:资源限制

Docker 默认不限制容器用多少 CPU 和内存,一个失控的进程能把整台机器拖死。小够教你看资源占用、设内存和 CPU 上限、swap 的取舍,以及小内存机器的调优思路。

我是小够,只推够用的 VPS。

Docker 有个反直觉的默认行为:容器可以用光主机的所有 CPU 和内存。某个应用内存泄漏,整台 VPS 被拖死,SSH 都连不上,只能去商家后台重启。设个上限,十分钟的事。

先看谁在吃资源

docker stats

实时显示每个容器的 CPU%、内存用量。输出列:

  • CPU %:占用的 CPU 比例,多核机器上可能超过 100%(比如 200% 就是用了 2 个核)。
  • MEM USAGE / LIMIT:用了多少 / 上限多少,没设上限的话 LIMIT 显示主机总内存。
  • NET I/O:网络收发,排查"谁在疯狂传数据"用它。
  • BLOCK I/O:磁盘读写,排查"谁在疯狂写盘"用它。
  • PIDS:进程数,异常飙高可能是 fork 炸弹或配置错误。
docker stats --no-stream   # 只看一眼,不持续刷新,适合写脚本或截图

看到 MEM USAGE 接近机器总内存,就是危险信号。看到 BLOCK I/O 持续很高,去查日志——八成是日志没做轮转(本月日志那篇)。

docker run 设限制

docker run -d --name web \
  --memory="512m" --memory-swap="1g" \
  --cpus="1.0" \
  nginx:alpine
  • --memory="512m":内存上限 512MB,超了进程会被 OOM killer 干掉——容器挂了,但机器保住了。这是关键取舍:宁可死一个容器,不死整台机器。
  • --memory-swap="1g":内存+交换分区总共 1G。不设的话,容器能把 swap 也吃光,整台机器照样卡死。
  • --cpus="1.0":最多用 1 个 CPU 核心。也可以写 --cpus="0.5" 半个核,适合"我就跑个小监控"的场景。

compose 里设限制

services:
  web:
    image: nginx:alpine
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
        reservations:
          memory: 256M

limits 是上限,reservations 是预留(软保证,调度时参考)。个人用户设 limits 就够了。

已经在跑的容器想补限制,不用重建:

docker update --memory 512m --cpus 1.0 web

docker update 在线生效,排错那篇讲过它还能改重启策略,应急很好用。

怎么定数字:土办法

小够的土办法:先跑起来看 docker stats 一周,取峰值的 1.5 倍当上限。比如博客平时用 200MB,设 512M;MySQL 峰值 600MB,设 1G。别拍脑袋,也别抄别人的——每个人的应用和用量都不一样。

不同应用的参考(1 核 2G 机器,个人用量):

应用建议内存上限
Nginx/静态网站256M
WordPress512M
MySQL 8.01G
Redis256M
Portainer256M

1 核 1G 的小机器更要设:系统本身要留 200-300MB,剩下的分给容器,加起来别超过 800MB,留点余量给突发。上面的数字是参考,以你自己 docker stats 看到的为准,别人的数字是别人的。

内存超了会怎样

容器进程被 OOM killer 干掉,docker ps 看状态可能是 Restarting(如果你配了 restart 策略)——无限重启。这时候别只加内存,先看日志找泄漏原因:

docker logs 容器名 --tail 100
dmesg | grep -i "out of memory"

dmesg 里能看到内核杀进程的记录,确认是 OOM 还是应用自己崩了。加内存是治标,找到泄漏才是治本。PHP 应用内存泄漏多半是插件问题,一个一个禁用排查,比加内存管用。

swap:开还是不开

小内存 VPS 常纠结要不要开 swap。小够的看法:开,但别大。1-2G 的 swap 能在内存 spike 时救一命,避免直接 OOM。但别指望 swap 当内存用——swap 在磁盘上,慢两个数量级,频繁进 swap 等于机器卡死,只是"没死透"。

# 看 swap
free -h

商家模板一般自带 swap,没有的话自己加个 swapfile。配合 --memory-swap 把容器的 swap 用量也管住,别让容器把 swap 当内存敞开了用。

CPU 限制什么时候用

内存限制是保命,CPU 限制是"讲礼貌"。多容器共存时,一个容器把 CPU 跑满,其他容器就卡。比如定时任务跑备份时 CPU 100%,网站响应变慢。给批处理类容器设 --cpus="0.5",留一半给在线服务。Web 服务本身一般不用限 CPU,限了反而影响突发流量时的响应。