Docker Private Registry - Deleted all images, but still showing in catalog

Following the official documentation (https://docs.docker.com/registry/spec/api/#deleting-an-image) I have been able to successfully delete an image. As expected, after deleting, the image can no longer be pulled nor its manifest called via API.

I feel like I've got the hard part done, however the problem is that the repo is still listed under /v2/_catalog after the deletion is finished. I'm trying to fully purge the registry.

Here is my registry compose file:

registry:
  image: registry:2.5.2
  container_name: registry-test
  ports:
    - 5007:5000
  environment:
    REGISTRY_STORAGE: s3
    REGISTRY_HTTP_TLS_CERTIFICATE: /etc/cert.crt
    REGISTRY_HTTP_TLS_KEY: /etc/cert.key
    REGISTRY_STORAGE_S3_ACCESSKEY: ******
    REGISTRY_STORAGE_S3_SECRETKEY: ******
    REGISTRY_STORAGE_S3_REGION: us-west-1
    REGISTRY_STORAGE_S3_BUCKET: ******
    REGISTRY_STORAGE_S3_SECURE: "true"
    REGISTRY_STORAGE_DELETE_ENABLED: "true"
  volumes:
    - /dockerdata/volumes/registry-test/etc/cert.crt:/etc/cert.crt
    - /dockerdata/volumes/registry-test/etc/cert.key:/etc/cert.key
  restart: unless-stopped

Here is the high-level method on what I did to delete the image:

  1. Gather image digest: HEAD https://myprivateregistry:5001/v2/myimage/manifests/mytag with "Accept: application/vnd.docker.distribution.manifest.v2+json" added to the header on the call

  2. The call returns header key Docker-Content-Digest with a value such as sha256:b57z31xyz0f616e65f106b424f4ef29185fbd80833255d79dabc73b8eb873bd

  3. Using that value from step 2, run the delete call: DELETE https://myprivateregistry:5001/v2/myimage/manifests/sha256:b57z31xyz0f616e65f106b424f4ef29185fbd80833255d79dabc73b8eb873bd

  4. Registry API returns 202 Accepted

  5. Run garbage collection manually: registry garbage-collect /etc/docker/registry/config.yml

  6. Garbage collector deletes the associated blobs from disk (log omitted here, but it successfully deletes the blobs)

At this point I can confirm the blobs are completely deleted from disk and I can no longer call image details (like in step 1 above) so I thought I was done.

However, when running: /v2/_catalog my associated repo still lists (even though there are no images within it)! Obviously it cannot pull or be used, but how can I fully remove that repo from that list now that it has no images associated with it?

I don't see anywhere how to properly remove this on the API documentation page. Perhaps I'm missing it somewhere?

EDIT -

I wanted to add some more info on how the registry looks before and after the above deletion takes place.

Before the Delete Operation Above:

docker/registry/v2/repositories/myimage/_manifests/revisions/...
docker/registry/v2/repositories/myimage/_manifests/tags/... 
docker/registry/v2/repositories/myimage/_layers/sha256/... (5 layers listed)
docker/registry/v2/blobs/sha256/...

After the Delete Operation Above:

docker/registry/v2/repositories/myimage/_layers/sha256/... (5 layers listed)

So the only thing left over is the _layers directory with the same 5x layers listed. This seems to be the reason why it's still listed on _catalog

When I delete the myimage folder (from docker/registry/v2/repositories/myimage) then the repository is no longer shown in the _catalog

This seems to be a method to purge it from the _catalog listing. However - what if an image has 2x tags, yet only 1 is deleted - is there a reason to delete anything from _layers in that case? How would that be handled with multiple versions of an image? Obviously I can't just clobber the _layers directory as the final method since, in the real world, there will be many tagged versions of an image. So this needs to be done intelligently.

I am simply finding it hard to find any documentation on the maintenance/upkeep of the Docker registry nor the schema for the _layers subdirectory and why the garbage collector doesn't clean up that directory the same it does with manifests and blobs.


Solution 1:

After much research, there is no current method to remove the catalog entries fully via API only.

The v2 registry doesn't allow deleting only certain tags from an image

This means that the entire image is deleted. Deletion of tags is in an open PR for a future version of the Registry (https://github.com/docker/distribution/pull/2169)

What this means in regards to this question is that the proper method is to delete the image from the repo list is exactly as you assumed. Remove it from disk. (Such as rm -r v2/repositories/myimage where myimage is the image name that you deleted via API.)

It will then be removed from the repo list in _catalog and you're finished with your deletion process. There is no need to restart anything like another answer mentioned.

When the ability to delete specific tags from the registry is added, then this procedure will change. For now it's all or nothing.

Reference:

https://forums.docker.com/t/delete-repository-from-v2-private-registry/16767/5

https://github.com/docker/distribution/pull/2169

https://docs.docker.com/registry/spec/api/