Docker 磁盘空间自动化清理实战
前言
作为一名开发者或运维工程师,你是否经常遇到 Docker 磁盘空间不足的问题?随着容器化技术的广泛应用,Docker 镜像、容器和网络等资源会不断累积,占用大量磁盘空间。今天,我将分享一套完整的 Docker 自动清理方案,帮助你轻松管理 Docker 磁盘空间。
问题背景
在日常开发和生产环境中,Docker 会累积大量未使用的资源:
- 过时的镜像版本
- 停止的容器实例
- 未使用的网络和卷
- 构建缓存
这些资源如果不及时清理,可能导致磁盘空间告急,影响系统正常运行。手动清理既繁琐又容易遗忘,因此我们需要一套自动化解决方案。
解决方案概览
我们通过以下步骤实现 Docker 自动清理:
- 创建智能清理脚本
- 设置定时执行任务
- 建立完善的日志监控机制
实战步骤
第一步:创建智能清理脚本
我们首先创建一个功能全面的清理脚本,它不仅能清理3个月前的镜像,还能清理其他未使用的资源,并提供详细的操作日志。
bash
mkdir -p /usr/local/bin/docker-cleanup && cat > /usr/local/bin/docker-cleanup/cleanup.sh << EOF
#!/bin/bash
# Docker 3个月镜像清理脚本
echo "=============================="
echo "Docker 磁盘清理开始 - \$(date)"
echo "=============================="
# 记录开始时间
START_TIME=\$(date +%s)
# 1. 查看清理前磁盘使用情况
echo -e "\n1. 清理前 Docker 磁盘使用情况:"
docker system df
# 2. 清理3个月前的未使用镜像
echo -e "\n2. 清理3个月前的未使用镜像:"
docker image prune -a -f --filter "until=2160h" # 2160小时 = 3个月
echo "3个月前的镜像已清理"
# 3. 清理所有停止的容器
echo -e "\n3. 清理已停止的容器:"
docker container prune -f
echo "已停止的容器已清理"
# 4. 清理未使用的网络
echo -e "\n4. 清理未使用的网络:"
docker network prune -f
echo "未使用的网络已清理"
# 5. 清理构建缓存
echo -e "\n5. 清理构建缓存:"
docker builder prune -f
echo "构建缓存已清理"
# 6. 查看清理后磁盘使用情况
echo -e "\n6. 清理后 Docker 磁盘使用情况:"
docker system df
# 7. 计算并显示释放的空间
END_TIME=\$(date +%s)
DURATION=\$((END_TIME - START_TIME))
echo "=============================="
echo "清理完成 - \$(date)"
echo "执行时间: \${DURATION} 秒"
echo "=============================="
# 8. 发送清理报告到系统日志
logger "Docker 定期清理完成,耗时 \${DURATION} 秒"
exit 0
EOF
脚本功能详解:
- 时间过滤清理 :使用
--filter "until=2160h"参数,只清理3个月前的镜像,保护近期使用的镜像 - 全面清理:不仅清理镜像,还包括容器、网络、构建缓存
- 可视化报告:清理前后都显示 Docker 磁盘使用情况
- 性能监控:记录执行时间,方便性能优化
- 系统日志:将执行结果写入系统日志,便于集中监控
第二步:授权脚本执行权限
bash
chmod +x /usr/local/bin/docker-cleanup/cleanup.sh
这一步很关键,确保脚本有执行权限。建议使用 sudo 执行,因为 Docker 命令通常需要 root 权限。
第三步:配置 Crontab 定时任务
Crontab 是 Linux 系统的定时任务管理器,我们利用它来设置每日自动清理。
bash
# 编辑 crontab
sudo crontab -e
添加以下内容:
bash
# Docker 自动清理配置
# 每天凌晨6点执行清理(系统负载较低时段)
0 6 * * * /usr/local/bin/docker-cleanup/cleanup.sh >> /var/log/docker-cleanup.log 2>&1
# 每周一凌晨3点清理30天前的日志文件(防止日志文件过大)
0 3 * * 1 find /var/log/docker-cleanup-*.log -mtime +30 -delete
Crontab 时间表达式解释:
0 6 * * *:每天6:00执行>> /var/log/docker-cleanup.log 2>&1:将标准输出和错误输出都重定向到日志文件0 3 * * 1:每周一3:00执行-mtime +30:删除30天前的文件
第四步:验证配置
完成配置后,需要进行验证以确保一切正常工作。
bash
# 查询定时任务信息
sudo crontab -l
# 立即运行一次(测试用)
sudo /usr/local/bin/docker-cleanup/cleanup.sh
# 查看日志
tail -50 /var/log/docker-cleanup.log
测试时建议:
- 先手动执行脚本,检查输出是否符合预期
- 可以使用
docker system df查看清理前后对比 - 检查日志文件是否正确生成

进阶配置
方案一:增强日志功能
如果你需要更详细的日志,可以修改脚本的日志部分:
bash
# 在脚本开头添加日志配置
LOG_FILE="/var/log/docker-cleanup/$(date +%Y%m%d).log"
exec &> >(tee -a "$LOG_FILE")
方案二:邮件通知
想要接收清理报告?添加邮件通知功能:
bash
# 安装邮件客户端
sudo apt-get install mailutils -y
# 在脚本末尾添加
echo "清理报告" | mail -s "Docker清理完成 $(date)" your-email@example.com
方案三:安全备份机制
在清理前自动备份重要镜像:
bash
# 在清理脚本开头添加备份逻辑
BACKUP_DIR="/backup/docker-images"
mkdir -p $BACKUP_DIR
# 备份特定标签的镜像
docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>" | while read image; do
if [[ $image == *:latest ]] || [[ $image == *:stable ]]; then
echo "备份重要镜像: $image"
docker save -o "$BACKUP_DIR/$(echo $image | tr '/' '_' | tr ':' '_').tar" $image
fi
done
注意事项
1. 风险控制
- 测试环境先验证:在生产环境部署前,先在测试环境充分测试
- 使用 --dry-run :可以使用
docker image prune -a --dry-run --filter "until=2160h"预览将被删除的镜像 - 重要镜像保护:为重要镜像添加保护标签,避免被清理
2. 性能考虑
- 选择低峰时段:凌晨执行避免影响业务
- 监控执行时间:如果清理时间过长,考虑调整清理策略
- 磁盘空间预警:可以结合磁盘监控,空间不足时自动触发清理
3. 特殊情况处理
- 构建服务器:如果使用 Docker 进行持续集成,可能需要保留更长的构建缓存
- 生产环境:生产环境可能需要对清理策略更保守
- 多节点集群:在 Docker Swarm 或 Kubernetes 集群中,需要在所有节点部署
监控与维护
查看清理效果
bash
# 查看历史清理记录
grep "Docker 定期清理完成" /var/log/syslog
# 查看磁盘空间变化
df -h /var/lib/docker
# 查看镜像数量变化
docker images | wc -l
日志轮转配置
为防止日志文件过大,可以配置 logrotate:
bash
sudo nano /etc/logrotate.d/docker-cleanup
添加以下内容:
/var/log/docker-cleanup.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 root root
}
总结
通过以上配置,我们实现了一个全自动的 Docker 磁盘清理方案,具有以下优点:
- 自动化:无需人工干预,定时执行
- 安全可控:只清理3个月前的资源,保护重要数据
- 全面清理:覆盖镜像、容器、网络、缓存等多个维度
- 可追溯:完整的日志记录,便于问题排查
- 灵活可扩展:可以根据需要调整清理策略
这套方案已经在多个生产环境中稳定运行,有效解决了 Docker 磁盘空间问题。希望这篇文章能帮助你更好地管理 Docker 环境,让你的系统始终保持最佳状态。
扩展思考
如果你有更复杂的需求,可以考虑:
- 按项目清理:只清理特定项目的镜像
- 智能保留策略:根据使用频率自动决定保留哪些镜像
- 集群级清理:在 Docker Swarm 或 Kubernetes 集群中统一管理
- 与 CI/CD 集成:在流水线结束后自动清理临时资源
如果你有任何问题或改进建议,欢迎在评论区留言讨论!