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

作者: wencst 分类: docker,linux,云计算,微服务,架构设计 发布时间: 2019-07-22 16:52 阅读: 5,075 次

一、问题描述

我自己搭建了一个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,后续如有空闲时间,会逐渐补充如何搭建此服务。

 

直接点击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

如果文章对您有用,扫一下支付宝的红包,不胜感激!

欢迎加入QQ群进行技术交流:656897351(各种技术、招聘、兼职、培训欢迎加入)



Leave a Reply