为Docker构建缓存设置定时任务,是实现自动化运维、避免磁盘空间告警的常用方法。这里有几种成熟且灵活的方案
📝 方案一:使用Cron定时任务(最简单通用)
这是最常见的方法,通过编写脚本并添加到Cron中,可以灵活地控制清理策略。
1. 创建清理脚本
建议将脚本放在 /usr/local/bin/ 目录下,例如创建一个名为 docker-cleanup.sh 的文件。
sudo nano /usr/local/bin/docker-cleanup.sh
2. 编写脚本内容 这里提供两种常见的策略,你可以根据需要选择或组合:
-
策略A:固定清理(保留最近资源) 此脚本会定期清理超过一定时间(如24小时)未使用的Docker资源,并记录日志。
#!/bin/bash echo "===== 开始Docker清理 $(date) =====" >> /var/log/docker-cleanup.log # 清理所有未使用的容器、网络、镜像(悬空和未被引用的)以及构建缓存 # --filter "until=24h" 表示只清理24小时前创建的资源 docker system prune -a -f --filter "until=24h" >> /var/log/docker-cleanup.log 2>&1 # 如果你想单独清理构建缓存并保留一定大小,可以使用以下命令替代上面的docker system prune # docker builder prune -f --keep-storage 20GB >> /var/log/docker-cleanup.log 2>&1 echo "===== 清理完成 $(date) =====" >> /var/log/docker-cleanup.log -
策略B:基于阈值的清理(空间不足时触发) 此脚本更智能,只有当磁盘使用率超过设定阈值(如90%)时,才会执行清理。
#!/bin/bash THRESHOLD=90 CURRENT_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//') if [ "$CURRENT_USAGE" -gt "$THRESHOLD" ]; then echo "$(date): 磁盘使用率 ${CURRENT_USAGE}% 超过阈值 ${THRESHOLD}%,开始清理Docker。" >> /var/log/docker-cleanup.log # 执行清理命令 docker system prune -a -f >> /var/log/docker-cleanup.log 2>&1 # 或者清理构建缓存:docker builder prune -f else echo "$(date): 磁盘使用率 ${CURRENT_USAGE}%,无需清理。" >> /var/log/docker-cleanup.log fi
3. 赋予脚本执行权限
sudo chmod +x /usr/local/bin/docker-cleanup.sh
4. 添加到Crontab 编辑当前用户的crontab文件:
crontab -e
在文件末尾添加一行来定义执行时间。例如,每天凌晨2点执行脚本:
0 2 * * * /usr/local/bin/docker-cleanup.sh
0 2 * * *代表每天凌晨2:00。- 每周日凌晨2:00 可以写成
0 2 * * 0。
⚙️ 方案二:使用BuildKit自动垃圾回收(最智能)
如果不想依赖外部定时任务,可以配置Docker自带的BuildKit垃圾回收(GC)机制,让它自动管理构建缓存。
适用场景:使用默认的 docker 驱动程序,希望Docker守护进程自己管理缓存大小。
配置方法:
编辑Docker守护进程的配置文件 /etc/docker/daemon.json(如果文件不存在则新建)。
sudo nano /etc/docker/daemon.json
添加或修改 builder 属性:
{
"builder": {
"gc": {
"enabled": true,
"defaultKeepStorage": "20GB"
// 可选:如果你需要更精细的控制,可以定义策略数组
// "policy": [
// { "keepStorage": "10GB", "filter": ["unused-for=720h"] }
// ]
}
}
}
enabled: true:启用垃圾回收。defaultKeepStorage:这是最关键的设置,用于控制构建缓存的最大预留磁盘空间,默认为20GB。你可以根据服务器的磁盘大小进行调整,例如"50GB"或"10GB"。
保存文件后,重启Docker服务使配置生效:
sudo systemctl restart docker
之后,BuildKit会自动运行GC策略,确保构建缓存大小不会无限增长。
⏱️ 方案三:使用Systemd定时器(适用于Systemd系统)
对于使用Systemd的Linux发行版,可以使用Systemd定时器(Timer)来替代Cron,实现更细粒度的控制。
-
创建Service单元 (
/etc/systemd/system/docker-prune.service)[Unit] Description=清理Docker构建缓存和镜像 [Service] Type=oneshot ExecStart=/usr/bin/docker system prune -a -f --filter "until=24h" # 也可以指定只清理builder缓存 # ExecStart=/usr/bin/docker builder prune -f -
创建Timer单元 (
/etc/systemd/system/docker-prune.timer)[Unit] Description=每天凌晨1:30运行docker清理服务 [Timer] OnCalendar=*-*-* 01:30:00 Persistent=true [Install] WantedBy=timers.target -
启用并启动定时器
sudo systemctl enable docker-prune.timer sudo systemctl start docker-prune.timer
💡 最佳实践与注意事项
- Cron环境变量问题:Cron执行时环境变量与交互式Shell不同,可能会找不到
docker命令。建议在脚本开头显式声明PATH,或者将运行cron的用户加入docker组。# 在脚本开头添加 export PATH="/usr/bin:/bin:/usr/local/bin:$PATH" until过滤器的含义:docker system prune --filter "until=24h"中的until是基于资源的创建时间,而不是“最后使用时间”。如果你的构建非常频繁,这个参数依然有效,但可能不如基于“最后使用时间”的GC策略那么精准。- 谨慎清理:在生产环境中,
docker system prune -a会删除所有未被运行中容器使用的镜像。如果你的部署流程依赖于本地缓存的特定版本镜像,请务必谨慎。可以先在测试环境中验证脚本效果。 - 结合使用:你可以将 BuildKit自动GC 作为基础防线(保证缓存不爆炸),同时设置一个周期较长的 Cron任务(如每周)来清理更古老的镜像和容器,实现双重保障。