背景 2核2G 的小服务器,跑了 5 个容器:MariaDB、Adminer、两个 Flask、Uptime Kuma。
某天 SSH 上去,docker ps 发现一个容器不见了。日志里看到:
Killed process (mysqld) total-vm:xxxkB
OOM Killer 把 MariaDB 杀了。 原因 两个问题:
没有内存限制——每个容器都能吃光整机内存,互相抢占,最后 Linux 触发 OOM Killer 随机杀进程
日志没限制——Docker 默认把容器日志存在 /var/lib/docker/containers/,不轮转、不清理。跑几个月,几十 GB 没了 解决 内存限制 在 docker-compose.yml 里给每个服务加 mem_limit:
services:
db:
image: mariadb:latest
mem_limit: 512m # 数据库给多点
adminer:
image: adminer:latest
mem_limit: 128m # 管理界面,少点
dashboard_a:
build: .
mem_limit: 256m
dashboard_b:
build: .
mem_limit: 256m
uptime-kuma:
image: louislam/uptime-kuma:1
mem_limit: 256m
加起来约 1.4G,给系统留了 600M 空间,不会再 OOM。 日志轮转 每个服务加 logging 配置:
logging:
driver: "json-file"
options:
max-size: "10m" # 单个日志文件最大 10M
max-file: "3" # 最多保留 3 个
效果:每个容器日志最多占 30M(10M × 3),5 个容器总共 150M 封顶。不会无限增长。 重启生效
docker compose up -d
docker compose ps
验证 看内存限制生效:
docker stats --no-stream
输出里 MEM LIMIT 列会显示每个容器的上限。 看日志轮转生效:
# 查看某个容器的日志文件
sudo ls -lh /var/lib/docker/containers/<CONTAINER_ID>/
*-json.log 文件不会超过 10M,而且会有 .1、.2 的备份文件。 三个坑 坑 1:只在 docker run 时加了限制,忘了 compose
docker run 用 --memory=256m,compose 用 mem_limit: 256m。两套语法不一样,别混。
坑 2:忘了给数据库留大内存
MariaDB 默认要吃几百 M 的 InnoDB 缓冲池。给它 256M 会一直 OOM。数据库至少 512M。
坑 3:日志配置只改了部分服务
全部服务都要加 logging,包括 Nginx、数据库、Uptime Kuma。只改一个没用——其他容器照样把磁盘吃满。
生活糗事:今天爬山,爬到半山腰,肚子突然一阵翻江倒海。实在顶不住,我找了个自以为够隐蔽的角落,纸巾都掏出来了,裤腰带也解开了。结果下一秒,身后突然来了一波人。我只能当场把那股洪荒之力硬生生憋回去。成年人的世界,简直比异世界还不好玩。😭😭😭