Delete unused digests of docker images and save space
If you’re using your docker registry to push continuous updates you’ve probably noticed that the disk mount space for the registry is gradually growing.
It looks like it’s time to have a registry clean up. Here’s how to do it.
First, Let’s Get Familiar With the Jargon
One docker image can have multiple tags. Each image has a digest, which is a unique value. When you do continuous pushes (with updated content) to the same image in the registry, the image in the registry will end up with multiple digests.
A tag is composed of several layers. The list of the layers for that particular digest is called a manifest. There is a corresponding blob for each layer. There can also be layers which are not used by any of the tags — those are called abandoned or unused layers. Those corresponding blobs are also unused. We can delete them to gain some space on the disk.
As you can see, the layers are shared among manifests (tags) — each manifest maintains a reference to the layer. As long as a layer is referenced by one manifest, it cannot be garbage collected.
Digests of a docker repo can be found under RepoDigests after a docker inspect command.
eg : docker inspect my.docker.registry.com:5000/ubuntu:latest
"RepoDigests": ["my.docker.registry.com:5000/ubuntu@sha256:74a1b5f5c5d771cf3570fa0f050e0c827538b7fe1873bc88b85d56818df3f2bc"],
In order for garbage collector to delete the blobs, we need to make those blobs orphaned. We can achieve that with two methods.
- Using v2 registry REST API
- Manually deleting in filesystem using ‘rm’ command.
Method 01: Using registry REST API
For this, you need to know the docker image name and the digest you want to delete.
Invoke rest API
curl -v -X DELETE http://registryhost:reigstryport/v2/${docker_image_name}/manifests/${digest}
eg : curl -vk -X DELETE https://my.docker.registry.com:5000/v2/mytestdockerrepo/manifests/sha256:66675d81b9bd5eafc105832b78abb91cab975bbcf028ca4bce4afe73f66914ee
You should get a 202 Accepted for a successful invocation.
Then run garbage collector
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
registry — registry container name.
Method 02: Deleting in the file system
You need to delete two dirs.
rm -r <root>/v2/repositories/${name}/_manifests/tags/${tag}/index/sha256/${hash}rm -r <root>/v2/repositories/${name}/_manifests/revisions/sha256/${hash}
Here <root> means the the registry mount location where this registry container stores all the data in the file system.
eg : /var/lib/registry/docker/registry
If you have mounted this to one of your disks in host machine you can delete from there. Otherwise you will have to attach to the registry container by using docker attach command and delete directories.
Then run garbage collector:
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.ymlPlease note that when using Method 01, registry container should have
REGISTRY_STORAGE_DELETE_ENABLED=true
You can also pass that as a environmental variable with -e tag when starting the container or inside your dockerfile.
If you are using Method 02, at the time of deleting those dirs the docker registry should be in read-only mode. Nobody should push to registry.