Skip to Content
InfraLegacy: DOCR quota fix

DigitalOcean Container Registry Quota Fix Guide

Runbook for resolving DigitalOcean Container Registry storage quota errors — diagnosis, cleanup steps, and prevention.

Overview

Diagnosis and resolution path — start at the top and follow the branch that matches your situation.

Understanding the Quota Issue

DigitalOcean Container Registry (DOCR) has the following limits:

  • Starter Plan (Free): 500MB storage
  • Basic Plan: 5GB storage ($5/month)
  • Professional Plan: 20GB storage ($20/month)

If you’re hitting quota limits, it’s likely due to:

  1. Storage quota exceeded - Too many images/tags accumulated
  2. Pull rate limits - Too many image pulls per hour
  3. Large image sizes - Images taking up too much space

Option A: Using DigitalOcean Web UI

  1. Log in to DigitalOcean
  2. Go to Container Registry
  3. Click on your registry
  4. For each repository (oter-server, oter-web-app):
    • Click on the repository
    • Review all tags
    • Delete old/unused tags (keep only: latest, current version, and maybe last 2-3 versions)
    • Delete any untagged images

Option B: Using doctl CLI

# Install doctl if not already installed # macOS: brew install doctl # Linux: https://docs.digitalocean.com/reference/doctl/how-to/install/ # Authenticate doctl auth init # List all repositories doctl registry repository list # List tags for a repository doctl registry repository list-tags oter-server # Delete specific tags (keep only latest and current version) doctl registry repository delete-tag oter-server <old-tag-name> # Delete all tags except latest and current version (example) doctl registry repository list-tags oter-server | grep -v "latest\|v1.0.0" | xargs -I {} doctl registry repository delete-tag oter-server {}

Option C: Using Docker API

# Login to DOCR echo "YOUR_DOCR_TOKEN" | docker login registry.digitalocean.com -u "YOUR_DOCR_TOKEN" --password-stdin # List all tags (requires jq) curl -u "YOUR_DOCR_TOKEN:YOUR_DOCR_TOKEN" \ https://registry.digitalocean.com/v2/oter-server/tags/list | jq # Delete specific tag (DigitalOcean doesn't support direct API deletion, use doctl or UI)

Solution 2: Switch to GitHub Container Registry (GHCR) - Free Alternative

GitHub Container Registry offers:

  • Unlimited storage for public images
  • 500MB free storage for private images (per account)
  • No pull rate limits for authenticated users
  • Free for open source projects

Migration Steps:

  1. Update GitHub Actions workflows to use GHCR instead of DOCR:
# In .github/workflows/publish-server-release.yml # Replace DOCR with GHCR images: ghcr.io/${{ github.repository_owner }}/oter-server
  1. Update authentication in workflows:
- name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }}
  1. Update deployment scripts to pull from GHCR:
# In deploy scripts, change: IMAGE_REPO=ghcr.io/YOUR_USERNAME/oter-server
  1. Push existing images to GHCR:
# Tag existing image docker tag registry.digitalocean.com/oter-registry/oter-server:latest \ ghcr.io/YOUR_USERNAME/oter-server:latest # Login to GHCR echo "$GITHUB_TOKEN" | docker login ghcr.io -u YOUR_USERNAME --password-stdin # Push to GHCR docker push ghcr.io/YOUR_USERNAME/oter-server:latest

Solution 3: Upgrade DOCR Plan

If you want to stay with DOCR:

  1. Go to DigitalOcean → Container Registry
  2. Click on your registry
  3. Click Upgrade Plan
  4. Choose Basic ($5/month for 5GB) or Professional ($20/month for 20GB)

Solution 4: Implement Image Cleanup Automation

Add a cleanup step to your GitHub Actions workflow to automatically delete old tags:

- name: Clean up old images if: github.ref == 'refs/heads/main' run: | # Keep only latest, current version, and last 2 versions # Delete all other tags older than 30 days # This requires doctl or custom script

Solution 5: Optimize Image Sizes

Reduce image sizes to use less storage:

  1. Use multi-stage builds (already in your Dockerfiles)
  2. Remove unnecessary files from images
  3. Use .dockerignore to exclude unnecessary files
  4. Use distroless or alpine base images
  5. Compress layers where possible

For immediate relief:

  1. Clean up old images using DigitalOcean UI (Solution 1)
  2. Keep only essential tags: latest, current version, and last 2-3 versions

For long-term:

  1. Switch to GHCR (Solution 2) - Free and unlimited for most use cases
  2. Or upgrade DOCR (Solution 3) if you prefer staying with DigitalOcean

Quick Cleanup Script

Here’s a script to help clean up old tags (save as cleanup-docr.sh):

#!/bin/bash # Cleanup old DOCR tags - keeps latest, current version, and last N versions REGISTRY_NAME="oter-registry" # Your registry name REPOSITORY="oter-server" # Repository to clean KEEP_VERSIONS=3 # Number of versions to keep # Authenticate doctl auth init # Get all tags sorted by date (newest first) TAGS=$(doctl registry repository list-tags $REPOSITORY --format Tag --no-header | sort -r) # Keep latest KEEP_TAGS="latest" # Get current version (you may need to adjust this logic) CURRENT_VERSION=$(doctl registry repository list-tags $REPOSITORY --format Tag --no-header | grep "^v" | head -1) KEEP_TAGS="$KEEP_TAGS $CURRENT_VERSION" # Keep last N versions VERSION_TAGS=$(doctl registry repository list-tags $REPOSITORY --format Tag --no-header | grep "^v" | head -$KEEP_VERSIONS) KEEP_TAGS="$KEEP_TAGS $VERSION_TAGS" # Delete all other tags for tag in $TAGS; do if [[ ! " $KEEP_TAGS " =~ " $tag " ]]; then echo "Deleting tag: $tag" doctl registry repository delete-tag $REPOSITORY $tag fi done echo "Cleanup complete!"

Verification

After cleanup, verify storage usage:

  1. Go to DigitalOcean → Container Registry
  2. Check the storage usage indicator
  3. Should be well under 500MB if cleanup was successful