Home > Software engineering >  Delete docker images from nexus registry using api
Delete docker images from nexus registry using api

Time:12-24

There's a nexus setup running for docker registry. I'm struggling to delete old/unnecessary images from nexus setup using the APIs.So far I'm aware of below available APIs. There are 2 requirements:

  1. Delete images older than 30 days.
  2. Keep at least 5 tags of each image.

The delete api can only delete using the digest of the images but I"m not sure how to find exact one for the tags of images. Search api don't seem to work for docker images. Can someone please help?

## Search api https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api/search-api?_ga=2.253346826.2007475959.1640178248-1042170715.1640178248#SearchAPI-SearchComponents

## Find all catalog images under docker registery curl -u admin:adminPass -X "GET" nexus.example.com/v2/_catalog | jq

## Get all tags of an image curl -u admin:adminPass -X "GET" nexus.example.com/v2/abc-web-service-prod/tags/list

## Get manifests curl -u admin:adminPass -X "GET" "nexus.example.com/v2/abc-web-service-stage-2/manifests/5.2.6_1" | jq

## Delete by digest curl -i -u admin:adminPass -X "DELETE" "nexus.example.com/v2/abc-web-service/manifests/sha256:8829ce7278c1151f61438dcfea20e3694fee2241a75737e3a8de31a27f0014a5"

CodePudding user response:

Two things are missing from the "get manifests" example. First, if you include the http headers, you'll likely get the digest field, or you can skip the jq and pipe the result into a sha256sum to get the digest. But you also need to add an "Accept" header for the various media types of a manifest, otherwise the registry will convert it to an older schema v1 syntax which will not have the same digest. Here's an example that does the two v2 docker media types:

api="application/vnd.docker.distribution.manifest.v2 json"
apil="application/vnd.docker.distribution.manifest.list.v2 json"
curl -H "Accept: ${api}" -H "Accept: ${apil}" \
     -u admin:adminPass \
     -I -s "nexus.example.com/v2/abc-web-service-stage-2/manifests/5.2.6_1" 

The next issue you'll run into with your policy is the 30 day requirement. You can get the creation time on many images by pulling their image config blob (it's listed in the manifest), but that date will be when the image was created, not when it was pushed or last pulled. There have been suggestions to add API's to OCI to handle more metadata, but we're still a ways off from that, and further still to get registry providers to implement them. So you'd end up deleting things that are likely being used. Even the 5 tag rule can be problematic if several new tags are created working through bugs in CI and you age out the image currently deployed in production.

With that all said, some tooling that I work on called regclient may help. The regctl command gives you a way to script this in a shell, e.g.:

#!/bin/sh
registry="nexus.example.com"
cutoff="$(date -d -30days ' %s')"
for repo in $(regctl repo ls "$registry"); do
  # The "head -n -5" ignores the last 5 tags, but you may want to sort that list first.
  for tag in $(regctl tag ls "$registry/$repo" | head -n -5); do
    # This is the most likely command to fail since the created timestamp is optional, may be set to 0,
    # and the string format might vary.
    # The cut is to remove the " 0000" that breaks the "date" command.
    created="$(regctl image config "$registry/$repo:$tag" --format '{{.Created}}' | cut -f1,2,4 -d' ')"
    createdSec="$(date -d "$created" ' %s')"
    # both timestamps are converted to seconds since epoc, allowing numeric comparison
    if [ "$createdSec" -lt "$cutoff" ]; then
      # next line is prefixed with echo for debugging, delete the echo to run the tag delete command
      echo regctl tag rm "$registry/$repo:$tag"
    fi
  done
done

Note that I'm using "regctl tag rm" above, which is different from an image manifest delete you're seeing in the API. This will attempt to do an OCI tag delete API first, which likely isn't supported by your registry. It falls back to pushing a dummy manifest and deleting that. The alternative of deleting the current manifest the tag points to is you may delete more tags than intended (you could have 5 tags all pointing to the same manifest).

If you want to further automate this, regbot in that same repo lets you build a policy and run it on a schedule to constantly cleanup old images according to your rules.

In addition to regclient, there's also crane and skopeo that may also help in this space, but the features of each of these will vary.

CodePudding user response:

I found a great solution to this. https://github.com/andrey-pohilko/registry-cli

1. Create a docker image [name: registry-cli:1.0.1] using below Dockerfile


ADD requirements-build.txt /

RUN pip install -r /requirements-build.txt

ADD registry.py /

ENTRYPOINT ["/registry.py"]

2. Use below command to list down all images:tags in your private nexus registry. docker run --rm registry-cli:1.0.1 -l admin:adminPass -r http://nexus.example.com

3. To get all tags of a particular image. docker run --rm registry-cli:1.0.1 -l admin:adminPass -r http://nexus.example.com-i <name-of-the-image1> <name-of-the-image2>

4. To delete all old tags of a particular image but keep latest 10 tags. docker run --rm registry-cli:1.0.1 -l admin:adminPass -r http://nexus.example.com -i <name-of-the-image1> --delete

5. To delete all the old tags of all the images in the repository but keep 10 latest tags of each image docker run --rm registry-cli:1.0.1 -l admin:adminPass -r http://nexus.example.com --delete

6. If you wish to keep 20 images instead of 10 then use --num docker run --rm registry-cli:1.0.1 -l admin:adminPass -r http://nexus.example.com --delete --num 20

7. Once you're done deleting the older tags of the images, run task "delete unused manifests and docker images"

8. Post step:7, run compaction task to reclaim the storage.

  • Related