Skip to main content

Free Docker Registry Options (Excluding GitHub)

Analysis of free Docker registry alternatives since GitHub Packages is at capacity.

Summary Recommendation

For your use case (self-hosted infrastructure + private images):Docker Hub Free Tier - Best option

  • 1 private repository (enough for multi-tag strategy)
  • Unlimited public repositories
  • No bandwidth limits
  • Easy integration with existing tools

Provider: Docker Inc. Free Tier: Yes (with limits) Website: https://hub.docker.com/

Free Tier Limits

  • Private Repositories: 1
  • Public Repositories: Unlimited
  • Pulls: Unlimited (for authenticated users)
  • Pushes: Unlimited
  • Storage: No explicit limit (soft limit ~10GB total)
  • Bandwidth: Unlimited
  • Image Retention: Permanent

Multi-Tag Strategy

Since you only get 1 private repo, use tags for different environments:

# Build and push
tags: |
username/faiht-fetcher:latest
username/faiht-fetcher:sandbox-${{ github.sha }}
username/faiht-fetcher:prod-${{ github.sha }}

GitHub Actions Integration

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and Push
uses: docker/build-push-action@v6
with:
context: services/fetcher
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/faiht-fetcher:latest
${{ secrets.DOCKERHUB_USERNAME }}/faiht-fetcher:${{ github.sha }}

Pros

  • ✅ Industry standard, well-supported
  • ✅ No bandwidth limits
  • ✅ Easy setup
  • ✅ Good documentation
  • ✅ Works with self-hosted runners

Cons

  • ❌ Only 1 private repository
  • ❌ Requires Docker Hub account

Option 2: Quay.io

Provider: Red Hat Free Tier: Yes Website: https://quay.io/

Free Tier Limits

  • Private Repositories: Unlimited
  • Public Repositories: Unlimited
  • Storage: No explicit limit
  • Bandwidth: Unlimited
  • Image Retention: Permanent
  • Build Triggers: Yes (can auto-build from GitHub)

GitHub Actions Integration

- name: Login to Quay.io
uses: docker/login-action@v3
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_PASSWORD }}

- name: Build and Push
uses: docker/build-push-action@v6
with:
context: services/fetcher
push: true
tags: |
quay.io/${{ secrets.QUAY_USERNAME }}/faiht-fetcher:latest
quay.io/${{ secrets.QUAY_USERNAME }}/faiht-fetcher:${{ github.sha }}

Pros

  • Unlimited private repositories (best free tier!)
  • ✅ Advanced features (vulnerability scanning, geo-replication)
  • ✅ No bandwidth limits
  • ✅ Red Hat backed (reliable)

Cons

  • ❌ Less popular than Docker Hub
  • ❌ UI can be less intuitive

Option 3: GitLab Container Registry

Provider: GitLab Free Tier: Yes Website: https://gitlab.com/

Free Tier Limits

  • Private Repositories: Unlimited
  • Public Repositories: Unlimited
  • Storage: 10 GB (across all projects)
  • Bandwidth: Unlimited
  • Image Retention: Configurable
  • CI/CD Minutes: 400 minutes/month (can build images)

GitHub Actions Integration

You'd need to mirror your repo to GitLab or use GitLab CI/CD instead. Not recommended if you want to keep GitHub Actions.

Pros

  • ✅ Unlimited private repositories
  • ✅ Built-in CI/CD
  • ✅ 10GB storage

Cons

  • ❌ Requires mirroring GitHub repo to GitLab
  • ❌ CI/CD minutes limit (400/month)
  • ❌ Complicates workflow

Option 4: Oracle Cloud Infrastructure Registry (OCIR)

Provider: Oracle Cloud Free Tier: Yes (Always Free) Website: https://cloud.oracle.com/

Free Tier Limits

  • Private Repositories: Unlimited
  • Storage: 20 GB (across all regions)
  • Bandwidth: 10 TB outbound/month
  • Image Retention: Permanent
  • Regions: Available in all OCI regions

GitHub Actions Integration

- name: Login to OCIR
uses: docker/login-action@v3
with:
registry: <region>.ocir.io
username: ${{ secrets.OCI_USERNAME }}
password: ${{ secrets.OCI_AUTH_TOKEN }}

- name: Build and Push
uses: docker/build-push-action@v6
with:
context: services/fetcher
push: true
tags: |
<region>.ocir.io/<tenancy>/<repo-name>/faiht-fetcher:latest
<region>.ocir.io/<tenancy>/<repo-name>/faiht-fetcher:${{ github.sha }}

Pros

  • ✅ 20GB storage (generous)
  • ✅ Unlimited repositories
  • ✅ Oracle's "Always Free" tier (truly free, not trial)
  • ✅ Good for enterprise-level reliability

Cons

  • ❌ More complex setup (OCI account, tenancy, auth tokens)
  • ❌ Less popular/documented
  • ❌ Overkill for simple use case

Option 5: Self-Hosted Harbor (If you have infrastructure)

Provider: Self-hosted Free Tier: N/A (open source) Website: https://goharbor.io/

Requirements

  • Kubernetes cluster OR Docker Compose
  • Storage (you provide)
  • Domain + SSL certificate

Features

  • Truly unlimited (your infrastructure)
  • ✅ Enterprise features (vulnerability scanning, policy enforcement)
  • ✅ Full control
  • ✅ CNCF graduated project (reliable)

GitHub Actions Integration

- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: registry.yourdomain.com
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}

Pros

  • ✅ No limits (you control everything)
  • ✅ Enterprise features for free
  • ✅ Privacy (your infrastructure)

Cons

  • ❌ Requires server/infrastructure
  • ❌ Maintenance overhead
  • ❌ Need domain + SSL

Comparison Table

RegistryPrivate ReposStorageBandwidthEase of SetupRecommendation
Docker Hub1~10GBUnlimited⭐⭐⭐⭐⭐ Easy✅ Best for simplicity
Quay.ioUnlimitedUnlimitedUnlimited⭐⭐⭐⭐ Good✅ Best free tier
GitLabUnlimited10GBUnlimited⭐⭐⭐ Medium❌ Requires mirroring
Oracle OCIRUnlimited20GB10TB/mo⭐⭐ Complex❌ Overkill
Self-Hosted HarborUnlimitedYour limitYour limit⭐ Hard❌ Only if you have infra

Since you only get 1 private repo on Docker Hub, use a multi-tag strategy:

Repository Structure

username/faiht-services:fetcher-sandbox-latest
username/faiht-services:fetcher-prod-latest
username/faiht-services:scheduler-sandbox-latest
username/faiht-services:scheduler-prod-latest
username/faiht-services:fetcher-<git-sha>
username/faiht-services:scheduler-<git-sha>

Updated Workflow for Docker Hub

# .github/workflows/_worker.yml
name: Reusable Docker Worker Deployment

on:
workflow_call:
inputs:
service_name:
required: true
type: string
environment:
required: true
type: string
context_path:
required: true
type: string
image_name:
required: true
type: string
secrets:
DOCKERHUB_USERNAME:
required: true
DOCKERHUB_TOKEN:
required: true

jobs:
build-push:
runs-on: self-hosted
steps:
- uses: actions/checkout@v4

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and Push
uses: docker/build-push-action@v6
with:
context: ${{ inputs.context_path }}
file: ${{ inputs.context_path }}/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/faiht-services:${{ inputs.image_name }}-${{ inputs.environment }}-latest
${{ secrets.DOCKERHUB_USERNAME }}/faiht-services:${{ inputs.image_name }}-${{ github.sha }}

Migration Steps (From Private Registry to Docker Hub)

1. Create Docker Hub Account

# Sign up at https://hub.docker.com/signup
# Create access token at https://hub.docker.com/settings/security

2. Add GitHub Secrets

gh secret set DOCKERHUB_USERNAME --body "your-username"
gh secret set DOCKERHUB_TOKEN --body "dckr_pat_xxxxx"

3. Update Workflow File

Replace .github/workflows/_worker.yml with the updated version above.

4. Update Portainer/Docker Compose

Update image references:

# Before
image: 192.168.18.20:5000/faiht-fetcher-worker:latest

# After
image: username/faiht-services:fetcher-sandbox-latest

5. Test Deployment

# Trigger workflow
git commit --allow-empty -m "test: docker hub migration"
git push origin sandbox

Final Recommendation

Use Docker Hub with the multi-tag strategy for:

  • ✅ Simplicity
  • ✅ No migration complexity
  • ✅ Industry standard
  • ✅ Works perfectly with self-hosted runners
  • ✅ Free forever (Docker's commitment)

Alternative: Quay.io if you need:

  • ✅ Multiple private repositories
  • ✅ More advanced features
  • ✅ Slightly better free tier

Avoid: GitLab (too complex), Oracle OCIR (overkill), Harbor (unless you already have infrastructure)