Skip to content

Registry Cleanup

The cleanup image helps manage old container images in your registry using regctl.

Why Cleanup?

Each deployment creates new image tags (staging-abc123, prod-def456). Over time, these accumulate and consume storage. The cleanup tool automatically removes old images while keeping recent ones.

Configuration

Create a config.yaml with retention rules:

registry: registry.example.com

retention:
  # Default settings for all images
  default:
    keep_latest: 10
    keep_days: 30

  # Per-image rules
  rules:
    - image: my-hugo-site
      keep_latest: 5
      keep_tags:
        - "prod-latest"
        - "staging-latest"

    - image: another-site
      keep_latest: 3
      keep_tags:
        - "prod-latest"

Options

Field Description
registry Registry URL
retention.default.keep_latest Default number of tags to keep
retention.default.keep_days Default age limit in days
retention.rules[].image Image name
retention.rules[].keep_latest Tags to keep for this image
retention.rules[].keep_tags Tags to never delete

Usage

Run Manually

# Dry run (default) - shows what would be deleted
docker run -v $(pwd)/config.yaml:/config/config.yaml \
  -e REGISTRY_USERNAME=user \
  -e REGISTRY_PASSWORD=pass \
  ghcr.io/slauger/hugo-gitops-pipeline/cleanup:latest

# Actually delete
docker run -v $(pwd)/config.yaml:/config/config.yaml \
  -e REGISTRY_USERNAME=user \
  -e REGISTRY_PASSWORD=pass \
  -e DRY_RUN=false \
  ghcr.io/slauger/hugo-gitops-pipeline/cleanup:latest

Environment Variables

Variable Default Description
CONFIG_FILE /config/config.yaml Path to config file
DRY_RUN true Set to false to actually delete
REGISTRY_USERNAME - Registry username
REGISTRY_PASSWORD - Registry password

Kubernetes CronJob

Deploy as a scheduled job via ArgoCD:

apiVersion: v1
kind: ConfigMap
metadata:
  name: registry-cleanup-config
data:
  config.yaml: |
    registry: registry.example.com
    retention:
      default:
        keep_latest: 10
      rules:
        - image: my-hugo-site
          keep_latest: 5
          keep_tags:
            - "prod-latest"
            - "staging-latest"
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: registry-cleanup
spec:
  schedule: "0 3 * * 0"  # Every Sunday at 3:00 AM
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: cleanup
              image: ghcr.io/slauger/hugo-gitops-pipeline/cleanup:latest
              env:
                - name: DRY_RUN
                  value: "false"
              envFrom:
                - secretRef:
                    name: registry-credentials
              volumeMounts:
                - name: config
                  mountPath: /config
          volumes:
            - name: config
              configMap:
                name: registry-cleanup-config

See examples/cleanup-cronjob.yaml for a complete example.

Registry Requirements

Your registry must have deletion enabled:

  • Docker Registry: Set REGISTRY_STORAGE_DELETE_ENABLED=true
  • Harbor: Enabled by default
  • GHCR: Deletion via API supported

After cleanup, run garbage collection on your registry to reclaim disk space.