Introduction
A private Docker registry is a crucial component for organizations looking to maintain control over their container images while ensuring secure and efficient distribution. This guide explores how to set up and manage a private Docker registry using the official registry container with Minikube and k3s environments.
Whether you’re a developer working on local projects or a DevOps engineer managing container deployments, having a private registry gives you complete control over your container images without relying on public registries like Docker Hub.
In this comprehensive guide, we’ll walk through the setup, configuration, and maintenance of a private Docker registry, specifically focusing on integration with Minikube and k3s environments.
Getting Started
Prerequisites Checklist
Before beginning, ensure you have the following components installed and configured:
- Docker Engine (latest stable version)
- Minikube or k3s cluster
- kubectl command-line tool
- Basic understanding of container concepts
If you need to deploy a Kubernetes cluster for this read our Minikube or K3s deployment guides.
Basic Concepts Overview
A container registry serves as a repository for storing and distributing Docker images. It plays a central role in:
- Storing container images securely
- Managing image versions and tags
- Facilitating image distribution across environments
- Supporting local development workflows
Setting Up a Registry with Minikube
Using the Built-in Registry Addon
Minikube provides a convenient registry addon that simplifies the setup process:
minikube addons enable registry
This command creates a registry service accessible at localhost:5000
. Verify the setup with:
kubectl get pods -n kube-system | grep registry
Manual Deployment Method
For more control over the registry configuration, you can deploy it manually:
Create a persistent volume and claim:
# registry-storage.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: registry-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data/registry"
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Apply the storage configuration:
kubectl apply -f registry-storage.yaml
Deploy the registry with persistent storage:
# registry-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry-storage
mountPath: /var/lib/registry
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "100m"
volumes:
- name: registry-storage
persistentVolumeClaim:
claimName: registry-pvc
Create a service for the registry:
# registry-service.yaml
apiVersion: v1
kind: Service
metadata:
name: registry
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
Apply the deployment and service:
kubectl apply -f registry-deployment.yaml
kubectl apply -f registry-service.yaml
Configuration Validation Steps
Test the registry setup by:
Pushing a test image:
docker tag nginx:latest localhost:5000/test-nginx
docker push localhost:5000/test-nginx
Verifying the image listing:
curl http://localhost:5000/v2/_catalog
Setting Up Registry with k3s
Deployment Process
First, prepare the storage directory on your host:
sudo mkdir -p /data/registry
sudo chmod 755 /data/registry
Create the persistent volume and claim optimized for k3s:
# k3s-registry-storage.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: registry-pv
spec:
storageClassName: local-path
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/data/registry"
persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-pvc
spec:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
Create the registry configuration:
# registry-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: registry-config
data:
config.yml: |
version: 0.1
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
Apply storage and config resources:
kubectl apply -f k3s-registry-storage.yaml
kubectl apply -f registry-config.yaml
Deploy the registry with persistent storage:
# k3s-registry-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry-storage
mountPath: /var/lib/registry
- name: registry-config
mountPath: /etc/docker/registry/config.yml
subPath: config.yml
resources:
limits:
memory: "512Mi"
cpu: "500m"
requests:
memory: "256Mi"
cpu: "100m"
volumes:
- name: registry-storage
persistentVolumeClaim:
claimName: registry-pvc
- name: registry-config
configMap:
name: registry-config
Deploy the service:
# registry-service.yaml
apiVersion: v1
kind: Service
metadata:
name: registry
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
- Apply deployment and service:
kubectl apply -f k3s-registry-deployment.yaml
kubectl apply -f registry-service.yaml
Storage Validation Steps
Verify that persistent storage is working correctly:
# Push a test image
docker tag nginx:latest localhost:5000/test-nginx
docker push localhost:5000/test-nginx
# Verify the image is in the registry
curl http://localhost:5000/v2/_catalog
# Delete the registry pod to force a restart
kubectl delete pod -l app=registry
# Wait for the new pod to be ready
kubectl get pods -l app=registry
# Verify the image is still available after pod restart
curl http://localhost:5000/v2/_catalog
Security Setup
For production environments, implement:
TLS configuration using certificates:
kubectl create secret tls registry-tls --cert=tls.crt --key=tls.key
Basic authentication:
htpasswd -Bbn username password > auth/htpasswd
kubectl create secret generic registry-auth --from-file=auth/htpasswd
Configuration and Best Practices
Insecure Registry Setup
Configure Docker daemon to trust your registry:
{
"insecure-registries": ["localhost:5000"]
}
For k3s, add to /etc/rancher/k3s/registries.yaml
:
mirrors:
"localhost:5000":
endpoint:
- "http://localhost:5000"
Authentication Setup
Create user credentials:
mkdir auth
htpasswd -Bbn admin password > auth/htpasswd
Configure basic authentication in the registry:
auth:
htpasswd:
realm: basic-realm
path: /auth/htpasswd
Storage Considerations
- For production environments, consider using cloud-native storage solutions instead of hostPath
- Set resource limits for your PVC to prevent excessive storage consumption
- Implement regular backups of the registry data
- Monitor storage usage and set up alerts for when storage is nearly full
- Consider implementing image retention policies to manage disk space automatically
Working with Your Private Registry
Basic Operations
Push images to your registry:
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest
Pull images from your registry:
docker pull localhost:5000/myapp:latest
List available repositories:
curl -X GET http://localhost:5000/v2/_catalog
Maintenance and Operations
Regular Maintenance Tasks
Garbage collection:
registry garbage-collect /etc/docker/registry/config.yml
Health monitoring:
curl -X GET http://localhost:5000/v2/_catalog
kubectl get pods -l app=registry
Log management:
kubectl logs -f -l app=registry
Troubleshooting Guide
Common issues and solutions:
- Image Pull Errors
- Check registry accessibility
- Verify image tags
- Confirm authentication credentials
- Storage Issues
- Monitor disk space
- Run garbage collection
- Review retention policies
- Container “Creating” State
- Check PV/PVC binding status:
kubectl get pv,pvc
- Verify host directory permissions:
ls -la /data/registry
- Check pod events:
kubectl describe pod -l app=registry
- Review logs:
kubectl logs -l app=registry
Conclusion
A private Docker registry provides essential functionality for managing container images in Minikube and k3s environments. Key takeaways:
- Choose between built-in addons or manual deployment
- Implement proper persistent storage for durability
- Apply appropriate security measures
- Regular maintenance is crucial
- Monitor performance and storage
By following this guide, you’ll be able to set up, configure, and maintain a reliable private Docker registry that enhances your container development and deployment workflows in both Minikube and k3s environments.