1. Docker磁盘空间告急?先摸清家底再动手
每次看到服务器磁盘空间报警,我的第一反应不是直接开删,而是先搞清楚哪些文件在占用空间。就像整理杂乱的房间,你得先知道哪些是没用的废品,哪些是重要的资料。对于Docker系统,这个"摸底"过程尤为关键。
docker system df是我最常用的侦查命令,它能清晰展示Docker的整体磁盘使用情况。执行后你会看到类似这样的输出:
code复制TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 15 10 5.2GB 2.1GB (40%)
Containers 12 6 1.8GB 1.8GB (100%)
Local Volumes 5 3 750MB 300MB (40%)
Build Cache 32 0 1.2GB 1.2GB
这个表格透露了几个关键信息:
- Images:显示所有镜像占用的总空间,以及可以回收的空间(未被任何容器使用的镜像)
- Containers:包括运行中和停止的容器,注意停止的容器仍占用空间
- Local Volumes:数据卷的使用情况,这部分容易被忽视
- Build Cache:构建缓存往往占用惊人空间
进阶版命令docker system df -v会列出每个镜像、容器和数据卷的详细占用情况。我常用这个命令找出那些"体积超标"的镜像——有些测试用的临时镜像可能高达几个GB。
提示:在Linux系统上,配合
df -h查看磁盘整体使用率,再用du -sh /var/lib/docker/*定位Docker的具体存储路径,能快速找到空间占用大户。
2. 精准清理:四类Docker垃圾的清除策略
2.1 镜像清理:别让"僵尸镜像"吃掉你的空间
Docker镜像就像软件的安装包,用久了就会堆积大量过期版本。我见过一个生产环境,80GB的磁盘有60GB被废弃镜像占据。清理镜像有几种策略:
基础清理命令:
bash复制# 删除所有悬空镜像(无标签的中间层镜像)
docker image prune
# 删除所有未被容器使用的镜像(危险!确保没有重要镜像)
docker image prune -a
但直接使用-a参数风险太大,我推荐更安全的渐进式清理:
bash复制# 先列出所有镜像,按创建时间排序
docker images --format "{{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}" | sort -k 5 -h
# 交互式删除特定镜像
docker image rm $(docker images --filter "dangling=true" -q)
真实案例:某次清理时发现10个不同版本的nginx镜像,每个约150MB。通过分析容器使用情况,最终只保留最近两个版本,节省了1.2GB空间。
2.2 容器日志:静默的空间杀手
容器日志的增长往往悄无声息。曾有个Java应用的JSON日志文件半年内膨胀到47GB,直接撑爆磁盘。Docker日志默认存储在:
code复制/var/lib/docker/containers/<container-id>/<container-id>-json.log
安全清理方法:
bash复制# 查看日志大小排名前10的容器
docker ps --format "{{.Names}}" | xargs -I {} sh -c "echo {}; docker inspect --format='{{.LogPath}}' {} | xargs ls -hl"
# 清空单个容器的日志文件(不影响正在运行的容器)
truncate -s 0 $(docker inspect --format='{{.LogPath}}' 容器名)
更专业的做法是配置日志轮转,在/etc/docker/daemon.json中添加:
json复制{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
2.3 Overlay2目录:深入文件系统的清理
/var/lib/docker/overlay2是Docker存储容器分层文件系统的核心目录,也是最容易积累垃圾的地方。清理时需要特别注意:
- 先停止所有容器(生产环境请谨慎)
- 使用专用工具分析:
bash复制# 查看overlay2目录大小
du -h --max-depth=1 /var/lib/docker/overlay2 | sort -h
# 找出关联已删除镜像的残留层
docker system df -v | grep -B 3 'unused'
危险操作警示:直接删除overlay2下的文件可能导致数据损坏!正确做法是通过Docker命令清理:
bash复制docker system prune --volumes
2.4 构建缓存:CI/CD环境的空间黑洞
持续集成环境中,构建缓存可能占用数十GB空间。清理策略包括:
bash复制# 清除所有构建缓存
docker builder prune
# 保留最近使用的缓存(推荐)
docker builder prune --filter 'until=24h'
对于多阶段构建,可以在Dockerfile中主动清理中间层:
dockerfile复制FROM node:14 as builder
RUN npm install && npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# 显式清除builder阶段的缓存
RUN docker image rm node:14
3. 自动化清理方案:定时任务与智能脚本
3.1 安全清理脚本模板
这是我用了三年的安全清理脚本,特点是:
- 保留最近3天的数据
- 不删除正在使用的资源
- 记录清理日志
bash复制#!/bin/bash
DATE=$(date +%Y%m%d)
LOG="/var/log/docker-clean-$DATE.log"
echo "===== Docker清理开始 $(date) =====" | tee -a $LOG
# 清理过期镜像
docker image prune -a --force --filter "until=72h" | tee -a $LOG
# 清理停止的容器
docker container prune --force --filter "until=24h" | tee -a $LOG
# 清理构建缓存
docker builder prune --force --filter "until=24h" | tee -a $LOG
# 清理日志文件(保留最近100MB)
find /var/lib/docker/containers/ -name "*-json.log" -exec truncate -s 100M {} \; | tee -a $LOG
echo "===== 清理完成 磁盘空间信息 =====" | tee -a $LOG
df -h | tee -a $LOG
docker system df | tee -a $LOG
3.2 系统定时任务配置
将脚本设为每周日凌晨3点执行:
- 保存脚本为
/usr/local/bin/docker-clean.sh - 添加执行权限:
chmod +x /usr/local/bin/docker-clean.sh - 编辑crontab:
crontab -e - 添加行:
code复制0 3 * * 0 /usr/local/bin/docker-clean.sh
3.3 异常情况处理
当清理后空间仍未释放时,检查:
- 文件系统是否被进程占用:
lsof /var/lib/docker - 是否启用了磁盘配额:
repquota /var - 是否存在大体积卷:
docker volume ls -q | xargs docker volume inspect
4. 防患于未然:Docker存储最佳实践
4.1 存储驱动选择策略
不同的存储驱动对磁盘空间的影响巨大:
| 驱动类型 | 空间效率 | 性能 | 适用场景 |
|---|---|---|---|
| overlay2 | ★★★★ | ★★★★ | 通用推荐 |
| devicemapper | ★★ | ★★ | 旧版本兼容 |
| zfs | ★★★ | ★★★ | 大数据量场景 |
| btrfs | ★★★ | ★★ | 开发测试环境 |
查看当前驱动:
bash复制docker info | grep "Storage Driver"
4.2 生产环境配置建议
- 独立分区:为
/var/lib/docker创建单独的分区,避免影响系统盘 - 日志管理:所有容器统一配置日志轮转
json复制{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" } } - 镜像策略:
- 使用Alpine等小体积基础镜像
- 多阶段构建减少最终镜像大小
- 定期扫描镜像漏洞:
docker scan <image>
4.3 监控与告警方案
推荐Prometheus+Grafana监控方案,关键指标包括:
container_fs_usage_bytes:容器文件系统使用量container_fs_limit_bytes:容器文件系统限制docker_daemon_storage_space_used:Docker存储使用量
示例告警规则:
yaml复制- alert: DockerDiskSpaceCritical
expr: (sum(container_fs_usage_bytes{device=~"/dev/.*"}) by (instance) / sum(container_fs_limit_bytes{device=~"/dev/.*"}) by (instance)) * 100 > 85
for: 10m
labels:
severity: critical
annotations:
summary: "Docker disk space critical on {{ $labels.instance }}"
在多年的Docker运维中,我发现最有效的空间管理其实是预防性维护。建议建立以下习惯:
- 每周检查一次
docker system df输出 - 所有构建脚本包含
--rm参数:docker build --rm -t myapp . - 为CI/CD流水线设置构建缓存自动清理
- 重要数据永远不要只存在容器内,必须使用volume持久化
当磁盘真的爆满时,记住这个救命命令组合:
bash复制# 紧急释放空间(会停止所有容器!)
docker system prune -a --volumes --force
