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:
- Storage quota exceeded - Too many images/tags accumulated
- Pull rate limits - Too many image pulls per hour
- Large image sizes - Images taking up too much space
Solution 1: Clean Up Old Images (Recommended First Step)
Option A: Using DigitalOcean Web UI
- Log in to DigitalOcean
- Go to Container Registry
- Click on your registry
- 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:
- 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- 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 }}- Update deployment scripts to pull from GHCR:
# In deploy scripts, change:
IMAGE_REPO=ghcr.io/YOUR_USERNAME/oter-server- 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:latestSolution 3: Upgrade DOCR Plan
If you want to stay with DOCR:
- Go to DigitalOcean → Container Registry
- Click on your registry
- Click Upgrade Plan
- 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 scriptSolution 5: Optimize Image Sizes
Reduce image sizes to use less storage:
- Use multi-stage builds (already in your Dockerfiles)
- Remove unnecessary files from images
- Use .dockerignore to exclude unnecessary files
- Use distroless or alpine base images
- Compress layers where possible
Recommended Approach
For immediate relief:
- Clean up old images using DigitalOcean UI (Solution 1)
- Keep only essential tags:
latest, current version, and last 2-3 versions
For long-term:
- Switch to GHCR (Solution 2) - Free and unlimited for most use cases
- 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:
- Go to DigitalOcean → Container Registry
- Check the storage usage indicator
- Should be well under 500MB if cleanup was successful