Skip to content

Instantly share code, notes, and snippets.

@kwk
Forked from bjaglin/remove-orphan-images.sh
Last active February 17, 2023 23:50
Show Gist options
  • Star 87 You must be signed in to star a gist
  • Fork 29 You must be signed in to fork a gist
  • Save kwk/c5443f2a1abcf0eb1eaa to your computer and use it in GitHub Desktop.
Save kwk/c5443f2a1abcf0eb1eaa to your computer and use it in GitHub Desktop.
#!/bin/bash
JQPATH=$(which jq)
if [ "x$JQPATH" == "x" ]; then
echo "Couldn't find jq executable." 1>&2
exit 2
fi
set -eu
shopt -s nullglob
readonly base_dir=/var/lib/docker/registry
readonly output_dir=$(mktemp -d -t trace-images-XXXX)
readonly jq=$JQPATH
readonly repository_dir=$base_dir/repositories
readonly image_dir=$base_dir/images
readonly all_images=$output_dir/all
readonly used_images=$output_dir/used
readonly unused_images=$output_dir/unused
function info() {
echo -e "\nArtifacts available in $output_dir"
}
trap info EXIT ERR INT
function image_history() {
local readonly image_hash=$1
$jq '.[]' $image_dir/$image_hash/ancestry | tr -d '"'
}
echo "Collecting orphan images"
for library in $repository_dir/*; do
echo "Library $(basename $library)" >&2
for repo in $library/*; do
echo " Repo $(basename $repo)" >&2
for tag in $repo/tag_*; do
echo " Tag $(basename $tag)" >&2
tagged_image=$(cat $tag)
image_history $tagged_image
done
done
done | sort | uniq > $used_images
ls $image_dir > $all_images
grep -v -F -f $used_images $all_images > $unused_images
readonly all_image_count=$(wc -l $all_images | awk '{print $1}')
readonly used_image_count=$(wc -l $used_images | awk '{print $1}')
readonly unused_image_count=$(wc -l $unused_images | awk '{print $1}')
readonly unused_image_size=$(cd $image_dir; du -hc $(cat $unused_images) | tail -n1 | cut -f1)
echo "${all_image_count} images, ${used_image_count} used, ${unused_image_count} unused"
echo "Unused images consume ${unused_image_size}"
echo -e "\nTrimming _index_images..."
readonly unused_images_flatten=$output_dir/unused.flatten
cat $unused_images | sed -e 's/\(.*\)/\"\1\" /' | tr -d "\n" > $unused_images_flatten
for library in $repository_dir/*; do
echo "Library $(basename $library)" >&2
for repo in $library/*; do
echo " Repo $(basename $repo)" >&2
mkdir -p "$output_dir/$(basename $repo)"
jq '.' "$repo/_index_images" > "$output_dir/$(basename $repo)/_index_images.old"
jq -s '.[0] - [ .[1:][] | {id: .} ]' "$repo/_index_images" $unused_images_flatten > "$output_dir/$(basename $repo)/_index_images"
cp "$output_dir/$(basename $repo)/_index_images" "$repo/_index_images"
done
done
echo -e "\nRemoving images"
cat $unused_images | xargs -I{} rm -rf $image_dir/{}
@jwshea
Copy link

jwshea commented Nov 11, 2014

There's a nasty bug here, when /usr/bin/jq is unavailable, $used_images wont get populated...

Which effectively means $unused_images == $all_images

Net result, rm -rf $all_images

Nasty.

@kwk
Copy link
Author

kwk commented Mar 6, 2015

@jwshea, thanks for this hint. I will fix it.

@kwk
Copy link
Author

kwk commented Mar 6, 2015

@jwshea: fixed.

@Damianca
Copy link

Hey, is there a plan to adjust the script for registry v2?
Thanks.
Damian

@clarionhoover
Copy link

This doesn't work if your images are pushed to s3, right?

@yonitg-zz
Copy link

HI !
will you be updating this script for registry V2 ?

thanks !

@calh
Copy link

calh commented Aug 27, 2015

I'm seeing these errors when I try to run this script:

jq: error (at /tmp/trace-images-SEu3/unused.flatten:0): Cannot iterate over string ("ca2f482a1f...)
jq: error (at /tmp/trace-images-SEu3/unused.flatten:0): Cannot iterate over string ("cae158413e...)
jq: error (at /tmp/trace-images-SEu3/unused.flatten:0): Cannot iterate over string ("ce74cb8e58...)

My jq version is 1.5, is that a problem?

@calh
Copy link

calh commented Aug 27, 2015

I think I figured it out -- I downgraded to jq 1.4 and the script works now. Nevermind!

@burnettk
Copy link

There's a script that works with registry v2 at https://github.com/burnettk/delete-docker-registry-image.

@smiskiewicz1
Copy link

Thanks for this! Saved me a lot of work. I've created a fork that has a test option that is non-destructive.
https://gist.github.com/smiskiewicz1/32d8a5db0ab743ff2accebf8c988cd21

@fcbflying
Copy link

@smiskiewicz1
will it wok with registry v2?

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