Skip to content

Instantly share code, notes, and snippets.

@allex
Last active August 18, 2021 09:00
Show Gist options
  • Save allex/3aab7875e033815227dd313a79465e18 to your computer and use it in GitHub Desktop.
Save allex/3aab7875e033815227dd313a79465e18 to your computer and use it in GitHub Desktop.
#!/bin/sh
# helper for cleanup docker registry (based on api v2)
# by @allex_wang
# GistID: 3aab7875e033815227dd313a79465e18
# requires: [jq]
set -eu
scriptName=$(basename "$0")
REGISTRY=127.0.0.1:5000
REG_USER=
help() {
cat <<-HELP
${scriptName} [OPTIONS] -u=allex:passwd --registry=192.168.0.219:5000
Cleanup docker registry remnants (Based on registry api v2)
Options:
-r | --registry Registry endpoint service (default: $REGISTRY)
-u | --user Registry auth user/passwd pairs (eg. allex:123456)
-h | --help Display this help and exit
HELP
}
die() {
[ "${1-}" ] && echo >&2 "${1}"
exit "${2-1}"
}
while [ $# -gt 0 ]; do
OPT=$1
[ "$OPT" = "--" ] && break
[ "$OPT" = "${OPT#-*}" ] && {
args+=("$OPT")
shift
continue
}
if [ "${OPT##=*}" = "$OPT" ]; then
OPTARG="${2-}"
if [ "${OPTARG##-*}" = "${OPTARG}" ]; then
shift
else
OPTARG=
fi
else
OPT=$(echo "$1" | awk -F= '{print $1}')
OPTARG=$(echo "$1" | awk -F= '{print $2}')
fi
case $OPT in
-h | --help)
help
exit
;;
-r | --registry) REGISTRY=$OPTARG ;;
-u | --user) REG_USER=$OPTARG ;;
*)
echo "ERROR: unknown parameter \"$OPT\""
help
exit 1
;;
esac
shift
done
# Registry
if [ -z "$REGISTRY" ]; then
echo -n "Enter registry: "
read -r REGISTRY
fi
# Registry User:Passwd
if [ -z "$REG_USER" ]; then
read -rp "Enter authorization for registry ${REGISTRY}: " REG_USER
[ -n "$REG_USER" ] || die "abort."
if [ "${REG_USER#*:}" = "${REG_USER}" ]; then
read -sp "Enter host password for user '$REG_USER': "
[ -n "$REPLY" ] || die "abort."
REG_USER=$REG_USER:$REPLY
fi
fi
api() {
a=$1
shift
curl --user "${REG_USER}" -s http://${REGISTRY}/v2/$a "$@"
}
c_id=$(docker ps | awk 'match($2, /registry:.*/) {print $1}')
[ -n "$c_id" ] || exit 1
del_reg_storage() {
local target=$1
echo "delete repository $target"
docker exec -i "$c_id" rm -rf "/var/lib/registry/docker/registry/v2/repositories/$target"
}
cleanup_tag() {
repo="$1"
tag="$2"
echo "=> check $repo:$tag..."
digests="$(api "$repo/manifests/$tag" -H "Accept: application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.list.v2+json" | jq -r '.manifests[].digest' 2>/dev/null)"
(
set +e
cat <<-EOF | (while read -r t; do (api "$repo/manifests/$t" | grep "MANIFEST_UNKNOWN") && exit 2; done)
$digests
EOF
if [ $? -eq 2 ]; then
cat <<-EOF | (while read -r t; do (api "$repo/manifests/$t" -X DELETE; del_reg_storage "$repo/_manifests/versions/${t/:\/}"); done)
$digests
EOF
del_reg_storage "$repo/_manifests/tags/$tag"
(exit 2)
fi
)
return $?
}
# return false (with no-zero exit code) if repo tags not valid
check_tags() {
local repo=$1
if api $repo/tags/list | egrep '"tags":null|"NAME_UNKNOWN"' &>/dev/null; then
return 1
fi
return 0
}
cleanup() {
repositories=($(api "_catalog" | jq -r ".repositories|.[]"))
for i in "${repositories[@]}"; do
if ! check_tags $i; then
del_reg_storage "$i"
else (
set +eE
api $i/tags/list | jq -r ".tags|.[]" | (while read -a t; do (cleanup_tag "$i" "$t"); done)
if ! check_tags $i; then
del_reg_storage "$i"
fi
); fi
done
}
echo "cleanup registry..."
cleanup
echo "garbage-collect registry..."
docker exec "$c_id" registry garbage-collect /etc/docker/registry/config.yml &>/dev/null
echo "restart registry..."
docker restart $c_id &>/dev/null
echo "done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment