镜像仓库清理

仓库空间GC

当我们对仓库里的images进行删除时,会发现镜像虽然删除了,但是仓库的占用空间没有释放,这是因为我们没有对registry进行垃圾回收(GC),这里介绍下常用仓库的GC方法。

Docker Registry之删除镜像、垃圾回收

Docker仓库在2.1版本中支持了删除镜像的API,但这个删除操作只会删除镜像元数据,不会删除层数据。在2.4版本中对这一问题进行了解决,增加了一个垃圾回收命令,删除未被引用的层数据。本文对这一特性进行了体验,具体步骤如下。

docker registry 2.4+ 启动时要指定 REGISTRY_STORAGE_DELETE_ENABLED

上传测试镜像

1
2
3
4
5
6
7
8
➜  local_registry_backup docker push 127.0.0.1:5000/alpine
The push refers to repository [127.0.0.1:5000/alpine]
df64d3292fd6: Layer already exists
latest: digest: sha256:02892826401a9d18f0ea01f8a2f35d328ef039db4e1edcc45c630314a0457d5b size: 528
➜ local_registry_backup pwd
/tmp/local_registry_backup
➜ local_registry_backup du -sh
2.2M .

删除仓库镜像

删除registry比较复杂,需要先查到指定标签的镜像的digest (sha256校验和),再根据这个digest来删除。

下面以删除 alpine 镜像为例。

先执行以下命令找到该镜像的digest:

1
2
3
➜  local_registry_backup curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET  http://127.0.0.1:5000/v2/alpine/manifests/latest 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'

sha256:02892826401a9d18f0ea01f8a2f35d328ef039db4e1edcc45c630314a0457d5b

执行以下命令,根据digest删除镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  local_registry_backup curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/alpine/manifests/sha256:02892826401a9d18f0ea01f8a2f35d328ef039db4e1edcc45c630314a0457d5b
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> DELETE /v2/alpine/manifests/sha256:02892826401a9d18f0ea01f8a2f35d328ef039db4e1edcc45c630314a0457d5b HTTP/1.1
> Host: 127.0.0.1:5000
> User-Agent: curl/7.60.0
> Accept: application/vnd.docker.distribution.manifest.v2+json
>
< HTTP/1.1 202 Accepted
< Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
< Date: Sat, 29 Dec 2018 04:49:38 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 127.0.0.1 left intact

查询发现仓库大小没有变化,但是我们无法pull image了

1
2
3
4
5
➜  local_registry_backup du -sh 
2.2M .
➜ local_registry_backup docker pull 127.0.0.1:5000/alpine
Using default tag: latest
Error response from daemon: manifest for 127.0.0.1:5000/alpine:latest not found

垃圾回收(GC)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查询镜像仓库
➜ local_registry_backup docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
08c91d59c13a dockercloud/haproxy:1.6.2 "/sbin/tini -- docke…" 12 minutes ago Up 12 minutes 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:5000->5000/tcp, 1936/tcp tmp_haproxy_1
03ab836b2d85 konradkleine/docker-registry-frontend:v2 "/bin/sh -c $START_S…" 12 minutes ago Up 12 minutes 80/tcp, 443/tcp tmp_registry-ui_1
14090e30745e tmp_registry "/entrypoint.sh /etc…" 12 minutes ago Up 12 minutes 5000/tcp tmp_registry_1

# 执行垃圾回收
➜ local_registry_backup docker exec -it 14090e30745e /bin/registry garbage-collect /etc/docker/registry/config.yml
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/02/02892826401a9d18f0ea01f8a2f35d328ef039db4e1edcc45c630314a0457d5b go.version=go1.6.3 instance.id=b7a1f6e5-002c-4070-8271-4bf098451fed
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/19/196d12cf6ab19273823e700516e98eb1910b03b17840f9d5509f03858484d321 go.version=go1.6.3 instance.id=b7a1f6e5-002c-4070-8271-4bf098451fed
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/4f/4fe2ade4980c2dda4fc95858ebb981489baec8c1e4bd282ab1c3560be8ff9bde go.version=go1.6.3 instance.id=b7a1f6e5-002c-4070-8271-4bf098451fed
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4 go.version=go1.6.3 instance.id=b7a1f6e5-002c-4070-8271-4bf098451fed
# 仓库大小已经减小
➜ local_registry_backup du -sh
12K .

harbor

最新版本的harbor(1.7+) 支持在页面手动执行gc了。直接admin登录进管理界面,手动触发即可。
对于 1.6+ 的版本,

可以按照官方文档

首先我们在web界面上选择要删除的images点击delete。
CAUTION: If both tag A and tag B refer to the same image, after deleting tag A, B will also get deleted. if you enabled content trust, you need to use notary command line tool to delete the tag’s signature before you delete an image.

接下来,使用registry的垃圾回收(GC)删除repository的实际文件。在执行GC之前,确保没有人正在推送images或stop Harbour。如果有人在GC运行时push images,则可能会错误地删除镜像层,从而导致images损坏。因此,在运行GC之前,首选方法是首先停止Harbour。

1
2
3
$ docker-compose stop

$ docker run -it --name gc --rm --volumes-from registry goharbor/registry:2.6.2-photon garbage-collect --dry-run /etc/registry/config.yml

注意: –dry-run 不执行任何删除动作

确认输出结果后,执行删除并启动仓库。

1
2
3
$ docker run -it --name gc --rm --volumes-from registry goharbor/registry:2.6.2-photon garbage-collect  /etc/registry/config.yml

$ docker-compose start

参考文档

https://github.com/docker/docker.github.io/blob/master/registry/garbage-collection.md

https://github.com/goharbor/harbor/blob/v1.6.1/docs/user_guide.md#deleting-repositories

https://blog.csdn.net/nklinsirui/article/details/80705306#%E5%88%A0%E9%99%A4registry%E4%B8%AD%E7%9A%84%E9%95%9C%E5%83%8F