This is a simple example of a Docker Registry with Let's Encrypt SSL. It uses Caddy as a reverse proxy and Let's Encrypt for SSL.
Caution
This repo serves as a simple example of a Docker Registry with Let's Encrypt SSL. It isn't considered production-ready. We use this repo simply for testing purposes with other applications.
- π Automatic HTTPS - Let's Encrypt certificates via Caddy (zero configuration)
- π Basic Authentication - htpasswd-based user authentication
- π₯ Multi-user Support - Separate admin (read-write) and reader (read-only) accounts
- π Easy Setup - One-command deployment with Docker Compose
- π¦ Latest Registry - Uses Docker Registry v3 (OCI Distribution Spec compliant)
- π Auto-renewal - SSL certificates automatically renewed
- π HTTP/3 Support - Modern protocol support out of the box
# Copy environment template
cp env.example .env
# Edit with your domain and email
nano .envUpdate .env:
REGISTRY_DOMAIN=registry.example.com # Your actual domainOption A: Using the setup script (recommended)
./setup.shOption B: Manual setup
mkdir -p auth
# Create admin user (read-write)
docker run --rm --entrypoint htpasswd httpd:2 -Bbn admin YourPassword > auth/htpasswd
# Add reader user (read-only)
docker run --rm --entrypoint htpasswd httpd:2 -Bbn reader YourPassword >> auth/htpasswddocker-compose up -d# Check logs
docker-compose logs -f
# Test the endpoint (wait ~30 seconds for cert generation)
curl https://registry.example.com/v2/
# Should return: {} (after authentication)# Login
docker login registry.example.com
# Username: admin (or reader)
# Tag and push (admin only)
docker tag ubuntu:latest registry.example.com/myapp:latest
docker push registry.example.com/myapp:latest
# Pull (both users)
docker pull registry.example.com/myapp:latest- Docker and Docker Compose installed
- Domain name with DNS A record pointing to your server
- Ports 80 and 443 open on your firewall/security group
- Public IP address (required for Let's Encrypt validation)
| User | Access | Use Case |
|---|---|---|
admin |
Read-Write | Push and pull images |
reader |
Read-Only* | Pull images only |
# Login to registry
docker login registry.example.com
# Pull an image from Docker Hub
docker pull alpine:latest
# Tag for your registry
docker tag alpine:latest registry.example.com/alpine:latest
# Push to your registry
docker push registry.example.com/alpine:latest
# Pull from your registry
docker pull registry.example.com/alpine:latestAdd more users to the htpasswd file:
# Add a new user
docker run --rm --entrypoint htpasswd httpd:2 -Bbn newuser password >> auth/htpasswd
# Restart registry to apply changes
docker-compose restart registryWe're Dan and Jay - a two person team with a passion for open source products. We created Server Side Up to help share what we learn.
- π Blog - Get the latest guides and free courses on all things web/mobile development.
- π Community - Get friendly help from our community members.
- π€΅ββοΈ Get Professional Help - Get custom solutions built for your team.
- π» GitHub - Check out our other open source projects.
- π« Newsletter - Skip the algorithms and get quality content right to your inbox.
- π₯ Twitter - You can also follow Dan and Jay.
- β€οΈ Sponsor Us - Please consider sponsoring us so we can create more helpful resources.
If you appreciate this project, be sure to check out our other projects.
- The Ultimate Guide to Building APIs & SPAs: Build web & mobile apps from the same codebase.
- Building Multi-Platform Browser Extensions: Ship extensions to all browsers from the same codebase.
- Bugflow: Get visual bug reports directly in GitHub, GitLab, and more.
- SelfHost Pro: Connect Stripe or Lemonsqueezy to a private docker registry for self-hosted apps.
- AmplitudeJS: Open-source HTML5 & JavaScript Web Audio Library.
- Spin: Laravel Sail alternative for running Docker from development β production.
- Financial Freedom: Open source alternative to Mint, YNAB, & Monarch Money.

