别让一个容器吃掉整台 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 |
| WordPress | 512M |
| MySQL 8.0 | 1G |
| Redis | 256M |
| Portainer | 256M |
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,限了反而影响突发流量时的响应。