Skip to content

Instantly share code, notes, and snippets.

@svenXY
Forked from shepmaster/trace-images.sh
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svenXY/1ff698a2053938f0629b to your computer and use it in GitHub Desktop.
Save svenXY/1ff698a2053938f0629b to your computer and use it in GitHub Desktop.
#!/bin/bash
# forked from shepmaster/trace-images.sh
# added some logic and made it cron-able (as little output as possible)
hash jq 2>/dev/null || { echo >&2 "jq is required but was not found. Please run make sure it is in the path"; exit 1;}
shopt -s nullglob
# Reset all variables that might be set
interactive=0
verbose=0
dryrun=0
while [ "$#" -gt 0 ]; do
case $1 in
-h|-\?|--help)
show_help
exit
;;
-r|--registry)
if [ "$#" -gt 1 ]; then
base_dir=$2
shift 2
continue
else
echo 'ERROR: Please specify the path to the registry with -r|-registry.' >&2
exit 1
fi
;;
--registry=?*)
base_dir=${1#*=}
;;
-v|--verbose)
verbose=1
;;
-n|--dry-run)
dryrun=1
verbose=1
;;
-i|--interactive)
interactive=1
verbose=1
;;
*) # Default case: If no more options then break out of the loop.
break
esac
shift
done
if [ -z "$base_dir" ] ; then
# should never happen, but anyway...
echo 'ERROR: Please specify the path to the registry with -r|-registry.' >&2
exit;
fi
readonly output_dir=$(mktemp -d -t cleanup_docker_images-XXXX)
readonly jq=$(which jq)
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 cleanup() {
[ $verbose -eq 1 ] && echo "Cleaning up $output_dir"
rm -rf $output_dir
}
trap cleanup EXIT ERR INT
function image_history() {
local readonly image_hash=$1
$jq '.[]' $image_dir/$image_hash/ancestry | tr -d '"'
}
[ $verbose -eq 1 ] && echo "Collecting orphan images at $repository_dir"
for library in $repository_dir/*; do
[ $verbose -eq 1 ] && echo "Library $(basename $library)" >&2
for repo in $library/*; do
[ $verbose -eq 1 ] && echo " Repo $(basename $repo)" >&2
for tag in $repo/tag_*; do
[ $verbose -eq 1 ] && echo " Tag $(basename $tag)" >&2
tagged_image=$(cat $tag)
image_history $tagged_image
done
done
done | sort | uniq > $used_images
[ $verbose -eq 1 ] && echo -n "used_images: " && cat $used_images | wc -l
ls $image_dir > $all_images
[ $verbose -eq 1 ] && echo -n "all_images: " && cat $all_images | wc -l
#
grep -v -F -f $used_images $all_images > $unused_images || true
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=$( if [ $unused_image_count -gt 0 ] ; then \
cd $image_dir; du -hc $(cat $unused_images) | tail -n1 | cut -f1; \
else echo 0; fi
)
if [ $unused_image_count -le 0 ] ; then
[ $verbose -eq 1 ] && echo "no unused images.";
exit;
fi
[ $verbose -eq 1 ] && 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
[ $verbose -eq 1 ] && 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"
if [ $dryrun -eq 1 ]; then
echo "Dryrun - not overwriting $repo/_index_images"
else
cp "$output_dir/$(basename $repo)/_index_images" "$repo/_index_images"
fi
done
done
[ $verbose -eq 1 ] && echo "these are unused images:"
[ $verbose -eq 1 ] && cat $unused_images
[ $verbose -eq 1 ] && echo "${all_image_count} images, ${used_image_count} used, ${unused_image_count} unused"
[ $verbose -eq 1 ] && echo "Unused images consume ${unused_image_size}"
ok="N";
if [ $interactive -eq 1 ]; then
echo -e "\nRemove images,are you sure?[Y=yes]"
read ok;
else
ok='Y'
fi
if [ "$ok" = "Y" ] ; then
[ $verbose -eq 1 ] && echo "before cleanup:" && du -sm $base_dir
if [ $dryrun -eq 1 ]; then
echo "Dryrun - not deleting anything"
cat $unused_images | xargs -I{} echo rm -rf $image_dir/{}
else
cat $unused_images | xargs -I{} rm -rf $image_dir/{}
fi
[ $verbose -eq 1 ] && echo "after cleanup:" && du -sm $base_dir
else
[ $verbose -eq 1 ] && echo "do nothing"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment