dockerdocker-registry

Delete Tags from a private docker registry


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.


Solution

  • 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 variable REGISTRY_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:

    acceptM="application/vnd.docker.distribution.manifest.v2+json"
    acceptML="application/vnd.docker.distribution.manifest.list.v2+json"
    curl -H "Accept: ${acceptM}" \
         -H "Accept: ${acceptML}" \
         -I -s "https://registry.example.org/v2/${repo}/manifests/${tag}" 
    

    And then a delete request on that digest would delete the manifest, along with all tags that also point to it:

    curl -H "Accept: ${acceptM}" \
         -H "Accept: ${acceptML}" \
         -X DELETE -s "https://registry.example.org/v2/${repo}/manifests/${digest}" 
    

    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:

    curl -H "Accept: ${acceptM}" \
         -H "Accept: ${acceptML}" \
         -X DELETE -s "https://registry.example.org/v2/${repo}/manifests/${tag}" 
    

    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:

    regctl tag rm registry.example.org/image1:T12
    regctl tag rm registry.example.org/image2:T22
    regctl tag rm registry.example.org/image5:T22
    

    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:

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

    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.