feat(registry): daily GC cronjob — keep last 10 SHA tags per repo, prune layers

This commit is contained in:
Will Anderson
2026-03-29 19:26:10 -05:00
parent 4515fd7fba
commit bb8748d426
+104
View File
@@ -0,0 +1,104 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: registry-gc
namespace: registry
spec:
# Run daily at 3am
schedule: "0 3 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: registry-gc
image: registry:2
command:
- /bin/sh
- -c
- |
set -e
echo "Starting registry garbage collection..."
# Keep the last 10 tags per repo; delete the rest via registry API
REGISTRY_URL="http://registry:5000"
# Get all repositories
REPOS=$(wget -qO- "$REGISTRY_URL/v2/_catalog" | sed 's/.*"repositories":\[//;s/\].*//' | tr ',' '\n' | tr -d '"')
for repo in $REPOS; do
echo "Processing repo: $repo"
# Get all tags sorted by date (registry API returns unordered, use digest order)
TAGS=$(wget -qO- "$REGISTRY_URL/v2/$repo/tags/list" | sed 's/.*"tags":\[//;s/\].*//' | tr ',' '\n' | tr -d '"')
TAG_COUNT=$(echo "$TAGS" | grep -c . || true)
echo " $TAG_COUNT tags found"
# Separate SHA tags (40-char hex) from named tags (latest, etc.)
SHA_TAGS=$(echo "$TAGS" | grep -E '^[0-9a-f]{40}$' || true)
SHA_COUNT=$(echo "$SHA_TAGS" | grep -c . || true)
# Keep the 10 most recent SHA tags; delete older ones
KEEP=10
if [ "$SHA_COUNT" -gt "$KEEP" ]; then
TO_DELETE=$(echo "$SHA_TAGS" | head -n "-$KEEP")
echo " Deleting $(echo "$TO_DELETE" | grep -c .) old SHA tags..."
for tag in $TO_DELETE; do
# Get the manifest digest
DIGEST=$(wget -qO- --server-response \
--header="Accept: application/vnd.docker.distribution.manifest.v2+json" \
"$REGISTRY_URL/v2/$repo/manifests/$tag" 2>&1 \
| grep -i "docker-content-digest" | awk '{print $2}' | tr -d '\r')
if [ -n "$DIGEST" ]; then
# Delete by digest
wget -q --method=DELETE \
"$REGISTRY_URL/v2/$repo/manifests/$DIGEST" && \
echo " Deleted $repo:$tag ($DIGEST)" || \
echo " Failed to delete $repo:$tag"
fi
done
else
echo " Skipping (only $SHA_COUNT SHA tags, keep threshold is $KEEP)"
fi
done
# Run the built-in GC to reclaim disk space from deleted layers
echo "Running storage garbage collection..."
/bin/registry garbage-collect /etc/docker/registry/config.yml --delete-untagged=false
echo "Done."
volumeMounts:
- name: data
mountPath: /var/lib/registry
- name: config
mountPath: /etc/docker/registry/config.yml
subPath: config.yml
volumes:
- name: data
persistentVolumeClaim:
claimName: registry-data
- name: config
configMap:
name: registry-gc-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: registry-gc-config
namespace: registry
data:
config.yml: |
version: 0.1
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000