Docker 定时清理缓存

0 阅读2分钟

为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,实现更细粒度的控制。

  1. 创建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
    
  2. 创建Timer单元 (/etc/systemd/system/docker-prune.timer)

    [Unit]
    Description=每天凌晨1:30运行docker清理服务
    
    [Timer]
    OnCalendar=*-*-* 01:30:00
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    
  3. 启用并启动定时器

    sudo systemctl enable docker-prune.timer
    sudo systemctl start docker-prune.timer
    

💡 最佳实践与注意事项

  1. Cron环境变量问题:Cron执行时环境变量与交互式Shell不同,可能会找不到docker命令。建议在脚本开头显式声明PATH,或者将运行cron的用户加入docker组。
    # 在脚本开头添加
    export PATH="/usr/bin:/bin:/usr/local/bin:$PATH"
    
  2. until过滤器的含义docker system prune --filter "until=24h"中的until是基于资源的创建时间,而不是“最后使用时间”。如果你的构建非常频繁,这个参数依然有效,但可能不如基于“最后使用时间”的GC策略那么精准。
  3. 谨慎清理:在生产环境中,docker system prune -a会删除所有未被运行中容器使用的镜像。如果你的部署流程依赖于本地缓存的特定版本镜像,请务必谨慎。可以先在测试环境中验证脚本效果。
  4. 结合使用:你可以将 BuildKit自动GC 作为基础防线(保证缓存不爆炸),同时设置一个周期较长的 Cron任务(如每周)来清理更古老的镜像和容器,实现双重保障。