Skip to content

Instantly share code, notes, and snippets.

@abelmferreira
Last active May 31, 2024 16:16
Show Gist options
  • Save abelmferreira/c38036f9642f2adf260ad068ac08f187 to your computer and use it in GitHub Desktop.
Save abelmferreira/c38036f9642f2adf260ad068ac08f187 to your computer and use it in GitHub Desktop.
#!/bin/sh
# This script remove tags from local registry, keeping just the n most recents tags
#
# based on: https://gist.github.com/jaytaylor/86d5efaddda926a25fa68c263830dac1?permalink_comment_id=4732942#gistcomment-4732942
# and on: https://stackoverflow.com/questions/31251356/how-to-get-a-list-of-images-on-docker-registry-v2
# Abels changes:
# - Not using jq utility, just curl and native linux binaries
# - Check based tag count, removing last n versions
# Function to check if has more than n tags and remove
check_tags_more_than_n_versions() {
# Get tag list, not sorted
local tagurl="https://${registry}/v2/${image}/tags/list"
echo "Searching image ${image} tags in registry ${registry} with url ${tagurl}"
local tags=$(curl -k -s -u $user:$password "$tagurl" | awk -F: '{print $3}' | sed -e 's/[][]//g' -e 's/\"//g' -e 's/ //g' -e 's/,/\n/g' | tr '}' '\n' | tr '{' '\n')
# Filter tags that has this string (opcional)
if [ -n "$only" ]; then
tags=$(echo "${tags}" | grep "$only")
fi
# Exclude tags that has this string (opcional)
if [ -n "$exclude" ]; then
tags=$(echo "${tags}" | grep -v "$exclude")
fi
local tagsWithTS=""
if [ -n "$tags" ]; then
# Get created timestamp for each tag
for tag in $tags; do
local created_time=$(curl -k -s -u $user:$password -H 'Accept: application/vnd.docker.distribution.manifest.v1+json' -X GET https://$registry/v2/$image/manifests/$tag | grep -i v1Compatibility | head -n1 | awk -F'created' '{print $2}' | awk -F'"' '{print $3}' | sed -e 's/\\//g')
created_time=$(echo $created_time | sed -e 's/T/ /g' | awk -F'.' '{print $1}')
local created_timestamp=$(date -d "$created_time" +%s)
tagsWithTS="${tagsWithTS}${created_timestamp}|${tag} "
done
#Sort tags by time stamp and remove from list keeplast values, keeping tags to remove
tagsWithTS=$(echo $tagsWithTS | xargs -n1 | sort -r -n -t'|' -k1)
tagsWithTS=$(echo $tagsWithTS | xargs -n1 | sed -n $((keeplast + 1)),1000p)
# Tags to remove
if [ -n "$tagsWithTS" ]; then
for tag in $tagsWithTS; do
tag=$(echo "$tag" | awk -F'|' '{print $2}')
echo "Tag $tag of image $image will be deleted..."
local tagdigest=$(curl -s -k -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')
local url="https://${registry}/v2/${image}/manifests/${tagdigest}"
curl -s -k -u "$user:$password" -X DELETE $url
done
else
echo "No tags to delete founded for image $image."
fi
else
echo "No tags found for image $image."
fi
}
HELPMSG="
Basic usage
$0 -r {registry_url} -i {image-name}
Options avaliable
-r registry url
-i image name
-k keep last n
-o keep only tags that contains this string
-e exclude tags if name contains this string
-u user
-p password
Examples
$0 -r registry.local:5000 -i project1
$0 -r registry.local:5000 -i project1 -e latest
"
while getopts ":r:i:k:o:e:u:p:" opt; do
case "$opt" in
r) registry="$OPTARG" ;;
i) image="$OPTARG" ;;
k) keeplast="$OPTARG" ;;
o) only="$OPTARG" ;;
e) exclude="$OPTARG" ;;
u) user="$OPTARG" ;;
p) password="$OPTARG" ;;
\?) echo "Opção inválida: -$OPTARG" >&2; exit 1 ;;
esac
done
# Set keeplast default value to 10
if [ -z "$keeplast" ]; then keeplast=10; fi
# Required params
if [ -z "$registry" ]; then echo "Error: Registry (-r) required"; echo "$HELPMSG"; exit 1; fi
if [ -z "$image" ]; then echo "Error: Image (-i) required"; echo "$HELPMSG"; exit 1; fi
check_tags_more_than_n_versions
@abelmferreira
Copy link
Author

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