在低配或入门级服务器(如 1 核 1GB 内存、10GB~20GB 磁盘)上部署容器化应用时,建立一套严谨的 Docker VPS 规范运维 体系是保障业务长期不中断的基石。很多新手站长直接使用默认配置运行容器,数周之后往往遭遇系统因磁盘 100% 耗尽而无法登录 SSH、数据库崩溃、或容器被 Linux OOM Killer 强制终结的惨状。
造成小硬盘 VPS 频频“爆盘”的最常见元凶包括:未配置大小限制的容器 JSON 日志文件持续膨胀数十 GB、构建镜像时残留的大量 Dangling 虚悬层、以及未能及时回收的卷缓存。
本文针对小内存与小存储 VPS 的苛刻环境,提供一套包含全局日志轮转、存储隔离、垃圾定时回收与应急爆盘排障的完整运维实践。
系统性服务器选型与安全调优指南,可先参阅站内支柱文档 VPS 建站与运维指南 与 常用 VPS 脚本工具。
隐患根源:为什么 Docker 默认配置容易让小 VPS 崩溃?
- 默认日志无上限(Uncapped JSON Logs):
- Docker 默认使用
json-file日志驱动,且默认不设文件大小上限; - 只要容器内的 Nginx、Node.js 或 Python 进程持续向 stdout/stderr 输出日志,宿主机/var/lib/docker/containers/<container-id>/<id>-json.log就会无限增长,直至吞噬整块硬盘; - 构建缓存与虚悬镜像堆积(BuildKit Cache & Dangling Images):
- 使用
docker build构建镜像或拉取新版本时,旧镜像会被标记为<none>(虚悬镜像),旧层不会自动删除; - 小内存 OOM 连锁反应:
- 如果未对容器设置
mem_limit,单个内存泄漏进程就会抢占所有物理内存,导致宿主机的 SSH 守护进程(sshd)直接被内核杀掉,造成假死。
防爆盘核心一:配置 daemon.json 全局日志轮转
最彻底的防范方式是在 Docker 守护进程层面强制启用全局日志轮转限制。所有新启动的容器都会自动继承该规则,无需在每个 compose 文件中重复编写。
创建或编辑 /etc/docker/daemon.json:
sudo mkdir -p /etc/docker
cat << 'EOF' | sudo tee /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2"
}
EOF
参数解析:
- max-size: "10m":单个日志文件最大不超过 10MB;
- max-file: "3":最多保留 3 个归档轮转文件(当前文件 + 2 个旧文件)。即单个容器产生的日志总量被严格锁死在 30MB 以内,彻底根除日志爆盘风险。
保存后平滑重载 Docker 守护进程(不重启正在运行的容器):
sudo systemctl daemon-reload
sudo systemctl reload docker || sudo systemctl restart docker
防爆盘核心二:清理已有历史日志与 overlay2 应急排查
如果服务器当前已经报警“No space left on device”,按以下顺序迅速释放空间:
1. 快速定位大文件所在位置
# 查看根分区使用率与挂载点
df -h
# 查看 /var/lib/docker 目录占用
sudo du -sh /var/lib/docker/* | sort -rh | head -n 10
2. 清空正在膨胀的容器日志(严禁直接 rm 删除正在打开的文件)
如果直接 rm *.log,被进程持有的文件句柄无法释放空间。正确的做法是使用 truncate 清空:
# 一键安全清空所有容器现有历史日志文件
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'
3. 系统级 Docker 垃圾全量清理
# 清理已停止的容器、未被使用的网络以及所有悬空镜像(<none>)
docker system prune -f
# 深度清理:同时清理未被任何容器使用的构建缓存与无用卷(慎用:确认重要数据已做外部卷持久化)
docker system prune -a --volumes -f
为了保障核心网站与数据库资产的安全,建议在日常运行自动化增量灾备,详见 VPS 自动化灾备实战:Rclone 跨云增量加密备份。
防爆盘核心三:Docker Compose 规范化编写模板
在编写 docker-compose.yml 时,必须强制指定资源配额与独立日志参数:
version: '3.8'
services:
web_app:
image: nginx:alpine
container_name: web_production
restart: unless-stopped
# 1. 严格限制物理内存与虚拟内存,避免小 VPS 发生 OOM 假死
deploy:
resources:
limits:
cpus: '0.80'
memory: 256M
# 2. 单独声明日志轮转(覆盖或双重加固 daemon.json)
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
# 3. 挂载持久化数据卷,排除日志写进容器读写层
volumes:
- /data/nginx/html:/usr/share/nginx/html:ro
- /data/nginx/logs:/var/log/nginx
防爆盘核心四:建立自动化系统级清理定时任务
在 /etc/cron.weekly/docker-maintenance 中建立每周自动化清理脚本:
#!/usr/bin/env bash
set -euo pipefail
# 每周日凌晨清理未引用的构建缓存与无用镜像
/usr/bin/docker image prune -af --filter "until=168h" >/dev/null 2>&1
/usr/bin/docker builder prune -af --filter "until=168h" >/dev/null 2>&1
赋予执行权限:
sudo chmod +x /etc/cron.weekly/docker-maintenance
同时结合系统网络栈调优,推荐配置 Linux VPS 开启 BBR 调优,保证容器对外提供 API 时的低丢包高吞吐。
常用空间诊断命令速查表
| 命令 | 功能用途 |
|---|---|
docker system df |
查看容器、镜像、卷和构建缓存的空间占用总览 |
docker system df -v |
查看具体每个镜像和卷的细粒度占用明细 |
docker stats --no-stream |
快速输出所有运行中容器的瞬时 CPU 与内存消耗 |
docker image prune -f |
删除所有无标签的虚悬镜像(Dangling images) |
docker volume prune -f |
删除未被任何容器挂载的匿名数据卷 |
官方来源与参考文档
更新记录
- 2026-09-03:建立首版 Docker 小内存与小硬盘 VPS 规范运维指南,涵盖 daemon.json 全局日志轮转限制、overlay2 应急清理、Compose 内存限额与自动化清理 Cron 任务。
评论