Docker Registry定期清理历史镜像

657 阅读2分钟

在上一篇写过,如何定期清理Docker集群下每个节点的过期无用的镜像 Docker定期清除无用镜像

实现思路

编写Python脚本,调用Registry开放的API接口。 获取镜像列表 -> 获取标签列表 -> 获取镜像详情 -> 调用删除接口。

前期准备

Registry默认是不允许删除镜像的,需要修改一下配置参数,在安装Registry 这篇文章写过,如何配置删除权限。

Python脚本

好久没有写Python代码了,重新捡起来试试。

import requests
import time
import os

class Docker(object):

    def restart(self):
        # 执行arbage-collect命令,删除未被引用的layer
        os.system("docker exec `docker ps | grep registry | awk '{print $1}'` registry garbage-collect /etc/docker/registry/config.yml")
        # 重启registry容器
        os.system("docker restart `docker ps | grep registry | awk '{print $1}'`")

    def get_repos(self,hub):
        get_repos_url = '%s/v2/_catalog' % (hub)
        res = requests.get(get_repos_url).json()
        return res['repositories']
        
    def __init__(self, hub):
        self.hub = hub

    @staticmethod
    def get_tag_list(hub, repo):
        # 获取这个repo的所有tags
        tag_list_url = '%s/v2/%s/tags/list' % (hub, repo)
        r1 = requests.get(url=tag_list_url)
        tag_list = r1.json().get('tags')
        return tag_list

    def main(self):
        hub = self.hub
        repos = self.get_repos(hub=hub)
        for repo in repos:
            self.delete_images(hub=hub, repo=repo)
        self.restart()

    def is_valid_date(self,str):
      '''判断是否是一个有效的日期字符串'''
      try:
        time.strptime(str, "%Y%m%d%H%M%S")
        return True
      except:
        return False
        """
        下面删除镜像的处理逻辑,可自定义编写
        我是根据时间戳作为镜像的标签,实现的思路是按照时间排序,保留最新的2个版本
        """
    def delete_images(self, hub, repo):
        tag_list = self.get_tag_list(hub=hub, repo=repo)
        print('开始处理 %s : %s' % (repo, tag_list))
        num = 0
        try:
            # 比如我所有服务的标签有三种:latest、SNAPSHOT、YYYYMMddHHmmss(时间戳)
          del_tag_list = []
            for tag in tag_list:
                # 标签是latest或者含有SNAPSHOT忽略删除
                if tag == 'latest' or 'SNAPSHOT' in tag :
                    print('%s 忽略 %s 删除' % (repo, tag))
                elif self.is_valid_date(str=tag):
                    print('%s 符合时间戳标签' % (tag))
                    del_tag_list.append(tag)
            # 按照时间排序
            del_tag_list.sort()
            # 保存最新2个版本
            for item in del_tag_list[:-2]:
                print('%s 删除 %s' % (repo, item))
                # 获取image digest摘要信息
                get_info_url = '{}/v2/{}/manifests/{}'.format(hub, repo, item)
                header = {"Accept": "application/vnd.docker.distribution.manifest.v2+json"}
                r2 = requests.get(url=get_info_url, headers=header, timeout=10)
                digest = r2.headers.get('Docker-Content-Digest')
                
                # 删除镜像
                delete_url = '%s/v2/%s/manifests/%s' % (hub, repo, digest)
                r3 = requests.delete(url=delete_url)
                if r3.status_code == 202:
                    num += 1
        except Exception as e:
            print(str(e))

        print('%s 共删除了%i个历史镜像' % (repo, num))
        print('------------------------------------------------------------')



if __name__ == '__main__':
    hub = 'http://192.168.1.200:5000'
    d = Docker(hub=hub)
    d.main()

上面Python脚本,参考了下面的博客,主要编写了需要删除的镜像过滤逻辑。

docker registry定期清理_mofei12138的博客-CSDN博客_docker registry 清理

Docker registry仓库历史镜像批量清理_ywq935的博客-CSDN博客

配置Crontab

# 进入任务编辑
crontab -e
# 添加定时任务,每天23:30 执行 "python /app/clear.py" 命令
30 23 * * * python /app/clear.py  >>/app/logs/clear.log 2>&1