Skip to content

Deploying a Docker Registry

Introduction

Docker Registry is a stateless, highly scalable server-side application that stores and lets you distribute Docker images. It’s an open-source implementation of the Docker Registry API that enables you to host your own private registry for storing and managing Docker container images. Whether you’re building a private container repository for your organization, creating a mirror of Docker Hub, or deploying a registry for CI/CD pipelines, Docker Registry provides a secure and reliable solution.

This comprehensive guide walks you through deploying Docker Registry on Klutch.sh using a Dockerfile, including installation, configuration, persistent storage setup, authentication, and security best practices.


Prerequisites

  • A Klutch.sh account (sign up here)
  • A GitHub repository for your Docker Registry deployment
  • Basic knowledge of Docker, containers, and registries
  • (Optional) Understanding of TLS certificates for secure registry access

Why Deploy Docker Registry on Klutch.sh?

Deploying your own Docker Registry on Klutch.sh offers several advantages:

  • Private image storage — Keep your proprietary container images secure and private
  • Reduced latency — Host images closer to your deployment infrastructure
  • Cost control — Avoid bandwidth costs from public registries
  • Full control — Customize storage backend, authentication, and access policies
  • CI/CD integration — Seamlessly integrate with your continuous deployment pipelines
  • Persistent storage — Klutch.sh volumes ensure your images persist across deployments

Project Layout

A typical Docker Registry deployment structure:

docker-registry/
├── Dockerfile
├── config.yml
├── auth/
│ └── htpasswd
└── README.md

The config.yml file contains registry configuration, and the auth/ directory holds authentication credentials if you enable basic authentication.


1. Sample Dockerfile for Docker Registry

Create a Dockerfile in your repository root:

# Use the official Docker Registry image
FROM registry:2.8
# Create directories for configuration and data
RUN mkdir -p /var/lib/registry /etc/docker/registry
# Copy custom registry configuration (optional)
COPY config.yml /etc/docker/registry/config.yml
# Expose the registry port (default: 5000)
EXPOSE 5000
# Set environment variables for storage
ENV REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
# Start the registry
CMD ["registry", "serve", "/etc/docker/registry/config.yml"]

This Dockerfile uses the official Docker Registry image version 2.8 and sets up the basic configuration. Klutch.sh will automatically detect this Dockerfile when you deploy.


2. Registry Configuration File

Create a config.yml file to configure your registry:

version: 0.1
log:
fields:
service: registry
level: info
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: 0.0.0.0:5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3

This configuration:

  • Sets up filesystem storage at /var/lib/registry
  • Enables image deletion capabilities
  • Configures the registry to listen on port 5000
  • Adds health check endpoints

3. Optional: Authentication Setup

For production deployments, you should enable authentication to protect your registry.

Creating Basic Authentication

First, create an htpasswd file locally using Docker:

Terminal window
# Create auth directory
mkdir auth
# Generate htpasswd file with username and password
docker run --rm --entrypoint htpasswd httpd:2 -Bbn username password > auth/htpasswd

Replace username and password with your desired credentials.

Update config.yml for Authentication

Add the following to your config.yml:

auth:
htpasswd:
realm: basic-realm
path: /etc/docker/registry/auth/htpasswd

Update Dockerfile for Authentication

Modify your Dockerfile to include the auth directory:

FROM registry:2.8
RUN mkdir -p /var/lib/registry /etc/docker/registry /etc/docker/registry/auth
COPY config.yml /etc/docker/registry/config.yml
COPY auth/htpasswd /etc/docker/registry/auth/htpasswd
EXPOSE 5000
ENV REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
CMD ["registry", "serve", "/etc/docker/registry/config.yml"]

4. Persistent Storage Configuration

Docker Registry stores container images in /var/lib/registry. To ensure your images persist across deployments and container restarts, you must attach a persistent volume.

Important: When configuring persistent volumes in Klutch.sh, you only need to specify the mount path and volume size. Volume names are managed automatically by the platform.

Volume Configuration

  • Mount path: /var/lib/registry
  • Recommended size: Start with 20GB minimum, scale based on expected image storage needs
  • Purpose: Stores all Docker image layers and manifests

Without persistent storage, all pushed images will be lost when the container restarts.


5. Environment Variables

You can configure Docker Registry using environment variables instead of or in addition to the config.yml file:

Essential Environment Variables

  • REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY — Path where images are stored (default: /var/lib/registry)
  • REGISTRY_HTTP_ADDR — Address and port to listen on (default: 0.0.0.0:5000)
  • REGISTRY_HTTP_SECRET — Secret for securing registry sessions (generate a random string)

Optional Environment Variables

  • REGISTRY_STORAGE_DELETE_ENABLED — Enable image deletion (set to true)
  • REGISTRY_LOG_LEVEL — Logging level (error, warn, info, debug)
  • REGISTRY_AUTH_HTPASSWD_REALM — Authentication realm name
  • REGISTRY_AUTH_HTPASSWD_PATH — Path to htpasswd file

Example Environment Variables Setup

When deploying on Klutch.sh, add these environment variables in the dashboard:

Terminal window
REGISTRY_HTTP_SECRET=your-random-secret-string-here
REGISTRY_STORAGE_DELETE_ENABLED=true
REGISTRY_LOG_LEVEL=info

Generate a secure random secret:

Terminal window
openssl rand -base64 32

6. Deploying to Klutch.sh

    1. Push Your Code to GitHub

      Commit your Dockerfile, config.yml, and any authentication files to your GitHub repository:

      Terminal window
      git init
      git add Dockerfile config.yml auth/
      git commit -m "Add Docker Registry configuration"
      git remote add origin https://github.com/yourusername/docker-registry.git
      git push -u origin main
    2. Create a New App in Klutch.sh

    3. Configure Your App

      • Create a new app within your project
      • Select your GitHub repository containing the Docker Registry configuration
      • Choose your main branch
      • Klutch.sh will automatically detect the Dockerfile in your repository root
    4. Configure Network Settings

      Docker Registry requires TCP traffic configuration:

      • Traffic Type: Select TCP (Docker Registry uses TCP protocol)
      • Internal Port: Set to 5000 (the port Docker Registry listens on inside the container)
      • External Port: Your app will be accessible on port 8000 (Klutch.sh standard TCP port for deployed apps)
    5. Add Persistent Volume

      Attach a persistent volume to ensure your Docker images persist:

      • In the app configuration, add a new volume
      • Mount Path: /var/lib/registry
      • Size: 20GB (minimum recommended, adjust based on your needs)
    6. Configure Environment Variables

      Add the following environment variables in the Klutch.sh dashboard:

      Terminal window
      REGISTRY_HTTP_SECRET=<your-random-secret>
      REGISTRY_STORAGE_DELETE_ENABLED=true
      REGISTRY_LOG_LEVEL=info
    7. Select Region and Resources

      • Choose your preferred deployment region
      • Select compute resources based on expected load
      • For production, choose at least 1GB RAM and 1 CPU core
      • Configure the number of instances (start with 1 for testing)
    8. Deploy

      Click “Create” to deploy your Docker Registry. Klutch.sh will:

      • Build your Docker image from the Dockerfile
      • Deploy the container with your configuration
      • Attach the persistent volume
      • Make your registry available at example-app.klutch.sh:8000

7. Connecting to Your Registry

After deployment, your Docker Registry will be accessible at example-app.klutch.sh:8000 (replace example-app with your actual app name).

Testing the Connection

Terminal window
# Test if registry is accessible
curl http://example-app.klutch.sh:8000/v2/
# Expected response: {}

Logging In (if authentication is enabled)

Terminal window
docker login example-app.klutch.sh:8000
# Enter username and password when prompted

Pushing an Image

Terminal window
# Tag an existing image for your registry
docker tag myimage:latest example-app.klutch.sh:8000/myimage:latest
# Push the image
docker push example-app.klutch.sh:8000/myimage:latest

Pulling an Image

Terminal window
docker pull example-app.klutch.sh:8000/myimage:latest

8. Using HTTPS with Custom Domains

For production deployments, you should use HTTPS to secure communication with your registry.

Setup Steps

    1. Add a custom domain to your Klutch.sh app (e.g., registry.yourdomain.com)
    2. Configure DNS records as instructed by the Klutch.sh dashboard
    3. Klutch.sh automatically provisions TLS certificates for your domain
    4. Update your Docker clients to use https://registry.yourdomain.com:8000

For detailed instructions, see the Custom Domains documentation.


9. Managing Registry Storage

Viewing Stored Images

Terminal window
# List all repositories in your registry
curl -X GET http://example-app.klutch.sh:8000/v2/_catalog
# List tags for a specific image
curl -X GET http://example-app.klutch.sh:8000/v2/myimage/tags/list

Deleting Images

If you enabled deletion in your config (REGISTRY_STORAGE_DELETE_ENABLED=true), you can delete images:

Terminal window
# Get the image digest
curl -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
http://example-app.klutch.sh:8000/v2/myimage/manifests/latest
# Delete by digest
curl -X DELETE http://example-app.klutch.sh:8000/v2/myimage/manifests/<digest>

Garbage Collection

To reclaim disk space after deleting images, run garbage collection:

Terminal window
# Run inside the container
registry garbage-collect /etc/docker/registry/config.yml

You can schedule this as a periodic job or run it manually via the Klutch.sh container console.


10. Advanced Configuration

Storage Backends

Docker Registry supports multiple storage backends. While the default filesystem storage works for most use cases, you can configure alternative backends:

  • S3 Compatible Storage — Use AWS S3, MinIO, or other S3-compatible services
  • Azure Blob Storage — Integrate with Microsoft Azure
  • Google Cloud Storage — Use GCP’s object storage

Example S3 configuration in config.yml:

storage:
s3:
accesskey: YOUR_ACCESS_KEY
secretkey: YOUR_SECRET_KEY
region: us-east-1
bucket: my-registry-bucket

Registry Mirroring

Configure your registry as a pull-through cache for Docker Hub:

proxy:
remoteurl: https://registry-1.docker.io
username: optional-dockerhub-username
password: optional-dockerhub-password

11. Security Best Practices

Authentication and Authorization

    1. Always enable authentication for production registries
    2. Use strong passwords and consider certificate-based authentication
    3. Regularly rotate credentials
    4. Implement role-based access control if using an authentication proxy

Network Security

    1. Use HTTPS with valid TLS certificates for all registry communication
    2. Restrict access using firewall rules or IP allowlists
    3. Use private networks when possible
    4. Enable rate limiting to prevent abuse

Storage Security

    1. Encrypt volumes containing sensitive images
    2. Regularly backup your registry data
    3. Implement scanning for vulnerabilities in stored images
    4. Set up monitoring and alerting for suspicious activity

Registry Hardening

    1. Keep the registry image updated to the latest version
    2. Disable the deletion API if not needed
    3. Implement resource limits to prevent denial of service
    4. Use read-only filesystems where possible
    5. Run regular security audits

12. Monitoring and Maintenance

Health Checks

Docker Registry includes built-in health check endpoints:

Terminal window
# Check registry health
curl http://example-app.klutch.sh:8000/v2/
# Detailed health check
curl http://example-app.klutch.sh:8000/debug/health

Logs

Monitor registry logs through the Klutch.sh dashboard to track:

  • Push and pull operations
  • Authentication attempts
  • Errors and warnings
  • Storage operations

Metrics

Enable Prometheus metrics in your config.yml:

http:
debug:
addr: 0.0.0.0:5001
prometheus:
enabled: true
path: /metrics

13. Troubleshooting

Common Issues

Problem: Cannot push images — “unauthorized: authentication required”

Solution: Ensure authentication is properly configured and you’ve logged in with docker login.

Problem: Registry returns 500 errors

Solution: Check logs for storage issues. Verify the persistent volume is properly mounted and has sufficient space.

Problem: Images disappear after redeployment

Solution: Confirm the persistent volume is attached to /var/lib/registry.

Problem: Slow push/pull operations

Solution: Increase compute resources or optimize network connectivity. Consider using a CDN or storage backend closer to your users.

Debugging Commands

Terminal window
# Check registry configuration
docker exec <container-id> cat /etc/docker/registry/config.yml
# View registry logs
docker logs <container-id>
# Check storage directory
docker exec <container-id> ls -lah /var/lib/registry
# Test registry API
curl -v http://example-app.klutch.sh:8000/v2/

14. Backup and Disaster Recovery

Backup Strategies

    1. Volume Snapshots — Regularly snapshot your /var/lib/registry volume
    2. Configuration Backup — Keep your config.yml and authentication files in version control
    3. Automated Backups — Set up scheduled jobs to copy critical data to object storage
    4. Image Mirroring — Consider replicating important images to a secondary registry

Backup Script Example

#!/bin/bash
# Backup script for Docker Registry
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/registry-$TIMESTAMP"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Copy registry data
cp -r /var/lib/registry/* "$BACKUP_DIR/"
# Compress backup
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
# Remove uncompressed backup
rm -rf "$BACKUP_DIR"
# Upload to object storage (example with aws cli)
# aws s3 cp "$BACKUP_DIR.tar.gz" s3://my-backup-bucket/

15. Scaling Your Registry

Horizontal Scaling

For high-availability deployments:

    1. Use a shared storage backend (S3, Azure Blob, GCS) instead of filesystem storage
    2. Deploy multiple registry instances behind a load balancer
    3. Configure session affinity for consistent user experience
    4. Implement a distributed cache layer

Vertical Scaling

    1. Increase CPU and memory allocation in Klutch.sh
    2. Use SSD-backed storage for better performance
    3. Optimize the persistent volume size based on usage patterns

Resources


Conclusion

Deploying your own Docker Registry on Klutch.sh provides you with a secure, scalable, and fully-managed solution for hosting private container images. With persistent volumes, TCP traffic support, and flexible configuration options, you can create a production-ready registry that integrates seamlessly with your development and deployment workflows.

Whether you’re building a private registry for your organization, creating a caching proxy for Docker Hub, or setting up a registry for CI/CD pipelines, this guide has covered everything you need to get started and scale your deployment.