72

docker registry服务器磁盘100%,该如何释放?

 4 years ago
source link: https://www.tuicool.com/articles/JbUNZn3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、问题描述

我自己搭建了一个docker registry私服,总磁盘有300G左右,有几年的时间,一直没动,没有扩展磁盘,也没有删除镜像。

最近忽然无法push镜像了,在服务器上查找一番,发现磁盘空间100%了。

二、所用环境

Ubuntu 16.04

registry 2.1.1

三、解决困难

1.registry默认配置不允许删除

1) 更改registry容器内/etc/docker/registry/config.yml文件

storage:
  delete:
    enabled: true

2.registry删除镜像时,仅删除索引,无法清理文件

1) 清理文件数据需要较复杂的运算,参见《了解docker registry的存储格式》(后续完善)

2) 升级registry到2.4.1,运用registry自带命令

docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

3.执行删除操作需要找到具体镜像的digest_hash值

1) 找出你想要的镜像名称的tag

$ curl -I -X GET <protocol>://<registry_host>/v2/<镜像名>/tags/list

2) 拿到digest_hash参数

$ curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET http://<仓库地址>/v2/<镜像名>/manifests/<tag>

3) 复制digest_hash

Docker-Content-Digest: <digest_hash>

4) 删除清单

$ curl -I -X DELETE <protocol>://<registry_host>/v2/<repo_name>/manifests/<digest_hash>

四、解决方案

1.registry官方推荐删除方案

1) 更改registry容器内/etc/docker/registry/config.yml文件

storage:
  delete:
    enabled: true

1) 找出你想要的镜像名称的tag

$ curl -I -X GET <protocol>://<registry_host>/v2/<镜像名>/tags/list

2) 拿到digest_hash参数

$ curl  --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET http://<仓库地址>/v2/<镜像名>/manifests/<tag>

例如:

$ curl  --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET http://10.109.252.221:5000/v2/wordpress/manifests/latest

3) 复制digest_hash

Docker-Content-Digest: <digest_hash>

4) 删除清单

$ curl -I -X DELETE <protocol>://<registry_host>/v2/<repo_name>/manifests/<digest_hash>

例如:

$ curl -I -X DELETE http://10.109.252.221:5000/v2/wordpress/manifests/sha256:b3a15ef1a1fffb8066d0f0f6d259dc7f646367c0432e3a90062b6064f874f57c

6) 删除文件系统内的镜像文件, 注意2.4版本以上的registry才有此功能

$ docker exec -it <registry_container_id> bin/registry garbage-collect <path_to_registry_config>

例如:

$ docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

2.简易版删除

1) 打开镜像的存储目录,如有-V操作打开挂载目录也可以,删除镜像文件夹

$ docker exec <容器名> rm -rf /var/lib/registry/docker/registry/v2/repositories/<镜像名>

2) 执行垃圾回收操作, 注意2.4版本以上的registry才有此功能

$ docker exec -it <registry_container_id> bin/registry garbage-collect <path_to_registry_config>

例如:

$ docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

3.删除时,遇到一个问题,一个镜像中tag数太多了,有的删除有的不删除

每次发版时,会在git branch名称后加一个时间戳,因此发版时,同一个git branch,最后一个时间戳为发版的时间戳

此处显示出awk功能的强大,一条语句解决问题:

cd /var/lib/registry/docker/registry/v2/repositories/<镜像名称>/_manifests/tags
ls | awk -F '.' '{print $1"."$2"."$3"."$4" "$5 }' | sort -k1rd | awk '{if(a[$1]<$2){b[$1][a[$1]]=1;a[$1]=$2}else{b[$1][$2]=1}}END{for(n in b){for(m in b[n]){if(m is not null) print n"."m}}}' | sort -k1rd | xargs -i rm -rf {}

逐条语句解释一下:

ls ——显示当前文件夹下的文件名

awk -F ‘.’ ‘{print $1″.”$2″.”$3″.”$4″ “$5 }’  ——此时将branch名称与时间戳区分开(awk应用功能之一,拆分同一个字段)

sort -k1rd ——k1表示用第一个字段,rd表示按字典序倒序

awk ‘{if(a[$1]<$2){b[$1][a[$1]]=1;a[$1]=$2}else{b[$1][$2]=1}}END{for(n in b){for(m in b[n]){if(m is not null) print n”.”m}}}’  ——这条语句有意思了,居然可以用awk写编程语句

详细拆分一下单引号内的语句,使用格式展开如下:

{
	if (a[$1] < $2) {            ##默认生成a[]数组,以$1作为index,以$2作为值,循环上一个管道输出,当原来存储值小于现有$2时
		b[$1][a[$1]] = 1;    ##默认生成b[][]二维数组,把$1和a[$1]作为二维数组的index,值不重要
		a[$1] = $2
	} else {                     ##当a数组原有存储值≥现有$2时
		b[$1][$2] = 1        ##记录$1和$2进入b[][]数组
	}                            ##两个判断结束后,b内的数组为分组结构,排除分组内最大值外都在b数组内
}
END {                                ##END标识初始化结束,开始输出
	for (n in b) {               ##第一层循环
		for (m in b[n]) {    ##第二层循环
			if (m is not null) print n"."m      ##将上一个awk输出的拆除的字段又拼接起来,还原了文件夹名称,判空是因为第一个判断时,将一个空的$2写入数组了
		}
	}
}

最后将过滤出的文件夹删除,使用管道xargs重定向删除。

4.使用hyper/docker-registry-web将数据删除

1) 修改/conf/config.yml,指定readonly为false,指定registry对应的服务:

registry:
   url: http://registry:5000/v2
   name: localhost
   readonly: false

2) 搭建docker-registry-web后,服务启动,用户登录,手动web端删除repository,后续如有空闲时间,会逐渐补充如何搭建此服务。

A7jYf2q.png!web

直接点击delete就可以删除了。

3) 执行垃圾回收操作, 注意2.4版本以上的registry才有此功能

$ docker exec -it <registry_container_id> bin/registry garbage-collect <path_to_registry_config>

例如:

$ docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

参考:https://shipengliang.com/software-exp/docker-registry%E4%BB%93%E5%BA%93%E9%95%9C%E5%83%8F%E5%88%A0%E9%99%A4%E6%96%B9%E6%B3%95.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK