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.mdThe 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 imageFROM registry:2.8
# Create directories for configuration and dataRUN 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 storageENV REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
# Start the registryCMD ["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.1log: fields: service: registry level: infostorage: cache: blobdescriptor: inmemory filesystem: rootdirectory: /var/lib/registry delete: enabled: truehttp: addr: 0.0.0.0:5000 headers: X-Content-Type-Options: [nosniff]health: storagedriver: enabled: true interval: 10s threshold: 3This 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:
# Create auth directorymkdir auth
# Generate htpasswd file with username and passworddocker run --rm --entrypoint htpasswd httpd:2 -Bbn username password > auth/htpasswdReplace 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/htpasswdUpdate 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.ymlCOPY 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 totrue)REGISTRY_LOG_LEVEL— Logging level (error,warn,info,debug)REGISTRY_AUTH_HTPASSWD_REALM— Authentication realm nameREGISTRY_AUTH_HTPASSWD_PATH— Path to htpasswd file
Example Environment Variables Setup
When deploying on Klutch.sh, add these environment variables in the dashboard:
REGISTRY_HTTP_SECRET=your-random-secret-string-hereREGISTRY_STORAGE_DELETE_ENABLED=trueREGISTRY_LOG_LEVEL=infoGenerate a secure random secret:
openssl rand -base64 326. Deploying to Klutch.sh
-
Push Your Code to GitHub
Commit your Dockerfile, config.yml, and any authentication files to your GitHub repository:
Terminal window git initgit add Dockerfile config.yml auth/git commit -m "Add Docker Registry configuration"git remote add origin https://github.com/yourusername/docker-registry.gitgit push -u origin main -
Create a New App in Klutch.sh
- Log in to Klutch.sh dashboard
- Navigate to Create a new project
- Give your project a meaningful name like “Docker Registry”
-
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
-
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)
-
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)
-
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=trueREGISTRY_LOG_LEVEL=info -
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)
-
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
# Test if registry is accessiblecurl http://example-app.klutch.sh:8000/v2/
# Expected response: {}Logging In (if authentication is enabled)
docker login example-app.klutch.sh:8000# Enter username and password when promptedPushing an Image
# Tag an existing image for your registrydocker tag myimage:latest example-app.klutch.sh:8000/myimage:latest
# Push the imagedocker push example-app.klutch.sh:8000/myimage:latestPulling an Image
docker pull example-app.klutch.sh:8000/myimage:latest8. Using HTTPS with Custom Domains
For production deployments, you should use HTTPS to secure communication with your registry.
Setup Steps
- Add a custom domain to your Klutch.sh app (e.g.,
registry.yourdomain.com) - Configure DNS records as instructed by the Klutch.sh dashboard
- Klutch.sh automatically provisions TLS certificates for your domain
- 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
# List all repositories in your registrycurl -X GET http://example-app.klutch.sh:8000/v2/_catalog
# List tags for a specific imagecurl -X GET http://example-app.klutch.sh:8000/v2/myimage/tags/listDeleting Images
If you enabled deletion in your config (REGISTRY_STORAGE_DELETE_ENABLED=true), you can delete images:
# Get the image digestcurl -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ http://example-app.klutch.sh:8000/v2/myimage/manifests/latest
# Delete by digestcurl -X DELETE http://example-app.klutch.sh:8000/v2/myimage/manifests/<digest>Garbage Collection
To reclaim disk space after deleting images, run garbage collection:
# Run inside the containerregistry garbage-collect /etc/docker/registry/config.ymlYou 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-bucketRegistry 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-password11. Security Best Practices
Authentication and Authorization
- Always enable authentication for production registries
- Use strong passwords and consider certificate-based authentication
- Regularly rotate credentials
- Implement role-based access control if using an authentication proxy
Network Security
- Use HTTPS with valid TLS certificates for all registry communication
- Restrict access using firewall rules or IP allowlists
- Use private networks when possible
- Enable rate limiting to prevent abuse
Storage Security
- Encrypt volumes containing sensitive images
- Regularly backup your registry data
- Implement scanning for vulnerabilities in stored images
- Set up monitoring and alerting for suspicious activity
Registry Hardening
- Keep the registry image updated to the latest version
- Disable the deletion API if not needed
- Implement resource limits to prevent denial of service
- Use read-only filesystems where possible
- Run regular security audits
12. Monitoring and Maintenance
Health Checks
Docker Registry includes built-in health check endpoints:
# Check registry healthcurl http://example-app.klutch.sh:8000/v2/
# Detailed health checkcurl http://example-app.klutch.sh:8000/debug/healthLogs
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: /metrics13. 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
# Check registry configurationdocker exec <container-id> cat /etc/docker/registry/config.yml
# View registry logsdocker logs <container-id>
# Check storage directorydocker exec <container-id> ls -lah /var/lib/registry
# Test registry APIcurl -v http://example-app.klutch.sh:8000/v2/14. Backup and Disaster Recovery
Backup Strategies
- Volume Snapshots — Regularly snapshot your
/var/lib/registryvolume - Configuration Backup — Keep your
config.ymland authentication files in version control - Automated Backups — Set up scheduled jobs to copy critical data to object storage
- 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 directorymkdir -p "$BACKUP_DIR"
# Copy registry datacp -r /var/lib/registry/* "$BACKUP_DIR/"
# Compress backuptar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
# Remove uncompressed backuprm -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:
- Use a shared storage backend (S3, Azure Blob, GCS) instead of filesystem storage
- Deploy multiple registry instances behind a load balancer
- Configure session affinity for consistent user experience
- Implement a distributed cache layer
Vertical Scaling
- Increase CPU and memory allocation in Klutch.sh
- Use SSD-backed storage for better performance
- Optimize the persistent volume size based on usage patterns
Resources
- Docker Registry Documentation
- Docker Registry GitHub Repository
- Klutch.sh Volumes Documentation
- Klutch.sh Networking Guide
- Klutch.sh Quick Start Guide
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.