How to Set Up a Private Docker Registry

A private Docker registry lets you store and distribute your own container images without relying on a public registry — useful for proprietary applications or organizations wanting full control over image storage.

Why Run Your Own Registry

  • Keep proprietary application images private, entirely under your own control
  • Avoid rate limits or availability dependencies on third-party public registries
  • Faster image pulls if your registry is closer to your deployment infrastructure

Prerequisites

  • Docker installed
  • A domain name (for proper TLS-secured registry access)

Step 1 — Run the Registry Container

docker run -d \
  --name registry \
  --restart unless-stopped \
  -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  registry:2

Step 2 — Add HTTPS via Reverse Proxy

Docker registries require HTTPS for non-localhost access by default — see How to Install Nginx Proxy Manager with Docker to route a domain with SSL to your registry.

Step 3 — Add Basic Authentication

mkdir auth
docker run --rm --entrypoint htpasswd registry:2 -Bbn myuser mypassword > auth/htpasswd
docker run -d \
  --name registry \
  --restart unless-stopped \
  -p 5000:5000 \
  -v registry-data:/var/lib/registry \
  -v $(pwd)/auth:/auth \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

Step 4 — Log Into Your Private Registry

docker login registry.yourdomain.com

Step 5 — Tag and Push an Image

docker tag myapp:1.0 registry.yourdomain.com/myapp:1.0
docker push registry.yourdomain.com/myapp:1.0

Step 6 — Pull the Image on Another Server

docker login registry.yourdomain.com
docker pull registry.yourdomain.com/myapp:1.0

Adding a Web UI (Optional)

The base registry has no built-in web interface — several open-source registry UI projects exist, providing browsable image listing/management if you want a friendlier interface beyond the command line.

Storage Considerations

Registry storage grows with every pushed image/tag — consider using object storage (see How to Set Up Self-Hosted S3-Compatible Object Storage with MinIO) as the registry's storage backend for more scalable, decoupled storage rather than relying solely on local VPS disk.

Setting Up Garbage Collection

docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml

Removes unreferenced image layers (from deleted/overwritten tags), reclaiming storage space that would otherwise accumulate indefinitely.

Integrating with CI/CD

See How to Build a Simple CI/CD Pipeline with GitHub Actions — configure your pipeline to push built images directly to your private registry as part of the deployment process.

Common Errors

"http: server gave HTTP response to HTTPS client" — Docker requires HTTPS for non-localhost registries by default; verify your reverse proxy is correctly serving HTTPS, not just forwarding to the registry's plain HTTP port without TLS termination.

Continue Reading

Browse more articles in Docker & Containers.

  • private docker registry, self hosted docker registry, docker registry setup, docker push private registry
  • 0 Users Found This Useful
Was this answer helpful?

Related Articles

How to Install Docker Engine on Ubuntu & Debian (Complete Guide)

Docker lets you package applications and their dependencies into lightweight, isolated containers...

How to Install Docker Compose on Ubuntu & Debian

Docker Compose lets you define and run multi-container applications from a single YAML file,...

Deploy Your First Docker Container: A Beginner's Walkthrough

With Docker installed, this hands-on walkthrough covers the core workflow you'll use constantly:...

How to Update Docker and Docker Compose Safely

Keeping Docker Engine and Compose updated brings security fixes, performance improvements, and...

Docker Compose Troubleshooting: Common Errors & Fixes

A reference guide to the Docker and Docker Compose errors you're most likely to encounter, with...