I am a new docker user, trying to learn something about docker.
I have a private docker registry. Inside it I have some images (example: I1,I2,I3,I4,I5). A lot of those images have tags inside it. Lets consider the following ones:
Image I1 - Tags: T11, T12, T13
Image I2 - Tags: T21, T22, T23, T24
Image I3 - Tags: T31, T32
Image I4 - Tags: T41, T42, T43, vT44
Image I5 - Tags: T51, T52
I want to delete, lets say, only Tags: T12, T22 and T52
, from docker registry.
How can I achieve it?
I´ve been reading a lot of posts but I still haven´t figure this out.
This ones seem to have some valuable content:
https://docs.docker.com/registry/spec/api/#deleting-an-image
Way to delete the images from Private Docker Registry
Although after even reading it I still could not figure out the way to do it.
If anyone can point me in the right direction I would appreciate it.
3
Answers
This is a bit more complex than it seems on the surface if you want to delete a tag and not an image manifest. First a prerequisite, your registry needs to permit deleting images which isn’t turned on by default in the
registry:2
image. The easy way to enable that is setting the environment variableREGISTRY_STORAGE_DELETE_ENABLED=true
on the container.Next, realize the difference between a tag and an image manifest. The manifest is represented by a digest, and is the json data that points to the image config and layers. A tag points to a manifest, but multiple tags may point to the same manifest, and a manifest may not have any tags pointing to it. If you delete a manifest, that also removes all tags that point to the manifest, so you need to be careful when deleting tags that you don’t accidentally delete a manifest referenced by tags you want to keep.
Therefore, the normal way to do this has issues. That normal way is to query the registry for the digest of the manifest you want to delete, and then delete that digest. You can get that digest from the headers:
And then a delete request on that digest would delete the manifest, along with all tags that also point to it:
However, if you want to delete just the tag, there is a delete tag API in distribution-spec, but few registries have implemented it. That delete would look like:
For registries that don’t support this, the best solution I’ve found is to push a dummy manifest that replaces the tag, and then delete that dummy manifest. That gets to be a bit much to handle with curl, there’s more media type headers I haven’t been including, and this doesn’t talk about authentication. For all of those challenges, I turn to writing it in Go. My own tool for that is regclient, and others like skopeo and crane also exist. From regclient, the regctl command to do this looks like:
Once the image is deleted, you likely want to clean the storage that is used, and for that you need to run a garbage collection while no other pushes are in progress (some will disable the registry or wait until a time they know uploads will not run). With the
registry:2
image, a GC command looks like:which will delete all untagged manifests, along with any unreferenced blobs.
Caution: untagged manifests in the distribution registry currently includes all child manifests of a multi-platform image. This means deleting untagged manifests will likely lead to data-loss if you have multi-platform images in your registry. There’s issue 3178 to track when this will be resolved.
While accepted answer is a good end solution, there is a simpler way to achieve this, without using the API: just delete the tag dirs manually from registry storage and then run the garbage-collect.
First identify where your registry stores the data. By default it goes to
/var/lib/registry
dir inside the container, but its probably binded to your host one way or the other. I am using docker-compose with data volume so in my case its located at:/var/lib/docker/volumes/registry_data/_data/registry
.You’ll find dirs named as your project tags in there, relative to above path:
v2/repositories/<repo_name>/_manifests/tags
Just delete the dirs which tag you dont want anymore. For example:
Once you are done with that, run the garbage-collect:
Your registry config file may be in some other path, but this is the default. Read more about the garbage collector from docs, but the gist is: the registry binary inside the container includes a garbage-collect command, but you have to run it yourself. Of course you can always let the crontab run it for you.
There are 2 steps required:
Tag Deletion
There are cleaner ways of doing this with the HTTP/REST API but you can execute a controlled deletion of old tags (>30days) with this command:
This will effectively "untag" the images. I highly recommend you run the
find
command without-exec rm
first to be sure of what you’re deleting!Kubernetes example (run from host machine):
Garbage Collection
Finally, run the
garbage-collection -m
executable.Or, from the host machine you can run it inside the container as follows (Kubernetes Example: