DEV Community

Łukasz Wolnik
Łukasz Wolnik

Posted on

Reclaiming free disk space from a private Docker repository

My private Docker repository just hit 200 GB in size. Below is an instruction on how to reclaim most of that disk space back by deleting old registry's tags.

First mark tags for deletion based on year. There's a regex that will match all tags from years 2021-2023:

#!/bin/bash

# Docker repository details
REGISTRY="https://docker.foo.com"
REPOSITORY="foo-frontend"
USERNAME="username"
PASSWORD="password"

# Get all tags
tags_json=$(curl -sk -u "$USERNAME:$PASSWORD" "$REGISTRY/v2/$REPOSITORY/tags/list")
tags_to_delete=$(echo "$tags_json" | jq -r '.tags[]' | grep -E '^202[123][0-9]{4}$')

# Delete tags
echo "Deleting tags from 2021 and 2022:"
while IFS= read -r tag; do
    echo "Deleting tag: $tag"
    ./delete-tag.sh "$tag" "$REPOSITORY"
    echo "Tag $tag deletion process completed."
done <<< "$tags_to_delete"

echo "All deletion processes completed."
Enter fullscreen mode Exit fullscreen mode

Now the script delete-tag.sh that gets digest for a given tag and marks it for deletion:

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "Error: Please provide a TAG value as an argument."
    exit 1
fi

# Set your registry URL, repository name, and credentials
REGISTRY_URL="https://docker.foo.com"
REPO_NAME="$2"
TAG="$1"
USERNAME="username"
PASSWORD="password"

echo "Received TAG: $TAG"

echo "Fetching manifest for ${REPO_NAME}:${TAG}"
MANIFEST=$(curl -s -k -u "${USERNAME}:${PASSWORD}" \
  -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  "${REGISTRY_URL}/v2/${REPO_NAME}/manifests/${TAG}")

echo "Debug - Manifest output:"
#echo "$MANIFEST"

if [[ $MANIFEST == *"errors"* ]]; then
  echo "Error fetching manifest:"
  echo "$MANIFEST" | jq .
else
  echo "Manifest found. Extracting digest..."
  CURL_OUTPUT=$(curl -s -k -u "${USERNAME}:${PASSWORD}" \
    -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
    -I "${REGISTRY_URL}/v2/${REPO_NAME}/manifests/${TAG}")

  echo "Debug - Curl output for digest:"
#  echo "$CURL_OUTPUT"

  DIGEST=$(echo "$CURL_OUTPUT" | grep -i Docker-Content-Digest | awk '{print $2}' | tr -d '\r\n')

  echo "Digest: ${DIGEST}"
  echo "Attempting to delete..."

  DELETE_RESPONSE=$(curl -s -i -k -u "${USERNAME}:${PASSWORD}" \
    -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
    -X DELETE "${REGISTRY_URL}/v2/${REPO_NAME}/manifests/${DIGEST}")

  echo "Delete response:"
#  echo "$DELETE_RESPONSE"

  if [[ $DELETE_RESPONSE == *"202"* ]]; then
    echo "Tag deleted successfully."
  else
    echo "Failed to delete tag. Check the response for more details."
  fi
fi

echo "Script execution completed."
Enter fullscreen mode Exit fullscreen mode

Lastly run docker ps to identify registry:2 container id and run:

docker exec <container_id> bin/registry garbage-collect /etc/docker/registry/config.yml
Enter fullscreen mode Exit fullscreen mode

Run below to confirm there's now more free space on your disk:

df -h
Enter fullscreen mode Exit fullscreen mode

Getting all repos from a Docker Registry

curl -k -u username:password -X GET https://docker.foo.com/v2/_catalog
Enter fullscreen mode Exit fullscreen mode

Getting all tags for a given regsitry

curl -k -u username:password -X GET http://docker.foo.com/v2/bar/tags/list
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay