Skip to content

Instantly share code, notes, and snippets.

@jaytaylor
Last active May 10, 2024 16:28
Show Gist options
  • Save jaytaylor/86d5efaddda926a25fa68c263830dac1 to your computer and use it in GitHub Desktop.
Save jaytaylor/86d5efaddda926a25fa68c263830dac1 to your computer and use it in GitHub Desktop.
One liner for deleting images from a v2 docker registry

One liner for deleting images from a v2 docker registry

Just plug in your own values for registry and repo/image name.

registry='localhost:5000'
name='my-image'
curl -v -sSL -X DELETE "http://${registry}/v2/${name}/manifests/$(
    curl -sSL -I \
        -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
        "http://${registry}/v2/${name}/manifests/$(
            curl -sSL "http://${registry}/v2/${name}/tags/list" | jq -r '.tags[0]'
        )" \
    | awk '$1 == "Docker-Content-Digest:" { print $2 }' \
    | tr -d $'\r' \
)"

If all goes well

* About to connect() to localhost port 5000 (#0)
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5000 (#0)
> DELETE /v2/my-image/manifests/sha256:14f6ecba1981e49eb4552d1a29881bc315d5160c6547fdd100948a9e30a90dff HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:5000
> Accept: */*
>
< HTTP/1.1 202 Accepted
< Docker-Distribution-Api-Version: registry/2.0
< X-Content-Type-Options: nosniff
< Date: Wed, 15 Nov 2017 23:25:30 GMT
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host localhost left intact

Garbage cleanup

Finally, invoke garbage cleanup on the docker-registry container.

For example:

docker exec -it docker-registry bin/registry garbage-collect /etc/docker/registry/config.yml
@lautitoti
Copy link

@DKroot Looks good, thanks!

Is it not an idea to select on max age or how many tags/versions of an image ?

I needed the same @di-rect , so I hope it helps you (or someone else) too :)

#!/bin/bash

# based on: https://gist.github.com/jaytaylor/86d5efaddda926a25fa68c263830dac1
# changes: 
# - Check for images older than a year 
-----------
# Function to check tags older than a year
check_tags_older_than_a_year() {
    local registry=$1
    local image=$2
    local user=$3
    local password=$4

    local tags=$(curl -s -u "$user:$password" "https://${registry}/v2/${image}/tags/list" | jq -r '.tags // [] | .[]')

    if [[ -n $tags ]]; then
        for tag in $tags; do
            # For manifests v2 uncomment the following line and comment the v1 version.
            # local created_time=$(curl -s -I -u "$user:$password" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "https://${registry}/v2/${image}/manifests/${tag}" | jq -r '[.history[]]|map(.v1Compatibility|fromjson|.created)|sort|reverse|.[0]')
            local created_time=$(curl -s -u $user:$password -H 'Accept: application/vnd.docker.distribution.manifest.v1+json' -X GET https://$registry/v2/$image/manifests/$tag | jq -r '[.history[]]|map(.v1Compatibility|fromjson|.created)|sort|reverse|.[0]')
            local created_timestamp=$(date -d "$created_time" +%s)
            local current_timestamp=$(date +%s)
            local age_days=$(( (current_timestamp - created_timestamp) / (60*60*24) ))

            if [[ $age_days -gt 365 ]]; then
                echo "Tag $tag of image $image is older than a year. Deleting..."
                # Uncomment the following line to actually delete the tag
                curl -s -u "$user:$password" -X DELETE "https://${registry}/v2/${image}/manifests/$(curl -s -I -u "$user:$password" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" "https://${registry}/v2/${image}/manifests/${tag}" | grep -i 'docker-content-digest' | awk -F': ' '{print $2}' | sed 's/[\r\n]//g')"
            fi
        done
    else
        echo "No tags found for image $image."
    fi
}

# Main function
main() {
    echo "Specify private image registry url without https://"
    read -r registry

    echo "List images, separated by space"
    read -r images

    echo "Registry User:"
    read -r user

    echo "Registry Password:"
    read -s password

    IFS=' ' read -r -a images_array <<< "$images"
    for image in "${images_array[@]}"; do
        echo "Checking tags for image $image..."
        check_tags_older_than_a_year "$registry" "$image" "$user" "$password"
    done
}

# Run the main function
main

@ehdis
Copy link

ehdis commented Mar 1, 2024

One liner :-)
skopeo delete docker://localhost:5000/apps/registry:latest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment