Contents
  1. 1. rm大法
  2. 2. 官方方法

docker registry是docker原生的镜像仓库,搭建和使用registry非常简单和轻量,我们就用这个原生registry放产出的docker image而没有选择harbor。
但是image tags不断增多,而清理历史tags的操作出现了无法真正清理的坑,我也不知道什么原因,可能是bug?按网上流行和官方doc的方法清理历史镜像是行不通的,迫使我用了粗暴的rm大法

rm大法

registry存放镜像的目录结构分2部分

  • 镜像元数据(manifests),存储在docker/registry/v2/repositories目录中
  • blobs,存储在docker/registry/v2/blobs目录中

manifests中记录了镜像引用了哪个blobs,如果没有manifests引用blobs,那这个blobs就可以在registry gc中清理掉。理解这个逻辑那就好办了,直接把不需要的manifests删掉然后做gc。
我们可以写个脚本reg_clean.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# 存放repository名字的文件位置,每行一个repo
REPOS="/regclean/repos.txt"

# 删除tag方法,保留最新的15个
function DelRepoTags()
{
REG_PATH="/var/lib/registry/docker/registry/v2/repositories/$1/_manifests/tags";
echo $REG_PATH;
ls -t $REG_PATH | tail -n +15 | while read DIR
do
rm -rf $REG_PATH/$DIR;
echo "Deleted $REG_PATH/$DIR"
done
}

cat $REPOS | while read repo
do
DelRepoTags $repo
done

# registry gc后才能真正删除blobs,释放空间
/bin/registry garbage-collect /etc/docker/registry/config.yml --delete-untagged=true

repos.txt :

1
2
3
4
ubuntu@k8s-m1:~/k8s/registry$ cat repos.txt 
repoA
repoB
repoC

把reg_clean.sh和repos.txt做成configmap挂载进registry pod,这样就可以在pod中清理旧tags

1
2
3
#!/bin/bash
REG_PO=`/usr/bin/kubectl get po |grep registry|awk '{print $1}'`
/usr/bin/kubectl exec $REG_PO -c registry -- /regclean/reg_clean.sh

可以看到mainfest deletion和blobs deletion信息
deletion信息

del blobs

官方方法

一开始使用dockerhub的registry:2.6.2版发现不行,后升级到2.7.1版测试结果也一样,这理只是记录一下操作流程。

  1. registry容器需要设置环境变量REGISTRY_STORAGE_DELETE_ENABLED=true,或者配置文件把删除镜像打开

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    version: 0.1
    log:
    fields:
    service: registry
    storage:
    cache:
    blobdescriptor: inmemory
    filesystem:
    rootdirectory: /var/lib/registry
    # 这里添加delete enable
    delete:
    enabled: true
    http:
    addr: :5000
    headers:
    X-Content-Type-Options: [nosniff]
    health:
    storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
  2. 使用镜像的name和reference,通过restful api进行删除,类似这样:

    1
    2
    3
    4
    # 获取镜像tag的reference
    curl /v2/<name>/manifests/<tag>
    # 删除
    curl -X DELETE -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' /v2/<name>/manifests/<reference>
  3. 执行registry garbage-collect释放磁盘空间

然而测试过多次并不可行,空间和tag信息都没有删除,通过registry web仍然可以看到repo的tag数目没有变化,磁盘空间也没有释放。

Contents
  1. 1. rm大法
  2. 2. 官方方法