Setting up a Docker Registry backed with Cloudflare R2
You can run a private Docker registry using Cloudflare R2 as your storage backend, in this tutorial we're going to configure it in a Kubernetes cluster. Creating bucket and access keys First, we need to create a R2 bucket where we'll store the Docker images. We also need an API access key and secret key to access the bucket. Once we have created the bucket and have both keys, we create a secret. vi registry-secrets.yaml apiVersion: v1 kind: Secret metadata: name: r2-secret type: Opaque data: ACCESS_KEY_ID: ACCESS_SECRET_KEY: And we apply the configuration. kubectl apply -f registry-secrets.yaml Deploying the Registry Once we've applied the secrets, we create the Registry deployment. vi registry-deployment.yaml Here is an example of the deployment, you should change some values to make it work in your cluster. apiVersion: apps/v1 kind: Deployment metadata: name: r2-registry spec: replicas: 1 selector: matchLabels: app: r2-registry template: metadata: labels: app: r2-registry spec: restartPolicy: Always containers: - name: registry image: registry:2 env: - name: REGISTRY_HEALTH_STORAGEDRIVER_ENABLED value: "false" - name: REGISTRY_STORAGE_DELETE_ENABLED value: "true" - name: REGISTRY_STORAGE value: s3 - name: REGISTRY_STORAGE_S3_REGION value: auto - name: REGISTRY_STORAGE_S3_REGIONENDPOINT value: https://.r2.cloudflarestorage.com - name: REGISTRY_STORAGE_S3_ENCRYPT value: "false" - name: REGISTRY_STORAGE_S3_SECURE value: "true" - name: REGISTRY_STORAGE_S3_CHUNKSIZE value: "104857600" - name: REGISTRY_STORAGE_S3_BUCKET value: - name: REGISTRY_STORAGE_S3_ACCESSKEY valueFrom: secretKeyRef: name: r2-secret key: ACCESS_KEY_ID - name: REGISTRY_STORAGE_S3_SECRETKEY valueFrom: secretKeyRef: name: r2-secret key: ACCESS_SECRET_KEY Once we've modified the deployment file, we apply it. kubectl apply -f registry-deployment.yaml Create service and ingress To access the registry, we might want to create a service and an ingress resource. The registry exposes at port 5000, so we create a service to that port. vi registry-service.yaml apiVersion: v1 kind: Service metadata: name: r2-registry spec: type: ClusterIP ports: - port: 5000 targetPort: 5000 protocol: TCP selector: app: r2-registry And we apply it. kubectl apply -f registry-service.yaml Next, we create an ingress resource so we can access the registry using our own domain or subdomain. vi registry-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: r2-registry annotations: nginx.ingress.kubernetes.io/proxy-body-size: "0" spec: rules: - host: registry.binarycomet.net http: paths: - path: / pathType: Prefix backend: service: name: r2-registry port: number: 5000 And we apply it. kubectl apply -f registry-ingress.yaml Next steps Now we have a working Docker registry that can be accessed via our own domain or subdomain, but it's not production-ready yet. You should add authentication so only the users authorized can access the registry. Also, it might be interesting to create an SSL certificate, so we don't have to register it as an insecure-registries everywhere we want to use it.
You can run a private Docker registry using Cloudflare R2 as your storage backend, in this tutorial we're going to configure it in a Kubernetes cluster.
Creating bucket and access keys
First, we need to create a R2 bucket where we'll store the Docker images. We also need an API access key and secret key to access the bucket.
Once we have created the bucket and have both keys, we create a secret.
vi registry-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: r2-secret
type: Opaque
data:
ACCESS_KEY_ID:
ACCESS_SECRET_KEY:
And we apply the configuration.
kubectl apply -f registry-secrets.yaml
Deploying the Registry
Once we've applied the secrets, we create the Registry deployment.
vi registry-deployment.yaml
Here is an example of the deployment, you should change some values to make it work in your cluster.
apiVersion: apps/v1
kind: Deployment
metadata:
name: r2-registry
spec:
replicas: 1
selector:
matchLabels:
app: r2-registry
template:
metadata:
labels:
app: r2-registry
spec:
restartPolicy: Always
containers:
- name: registry
image: registry:2
env:
- name: REGISTRY_HEALTH_STORAGEDRIVER_ENABLED
value: "false"
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
- name: REGISTRY_STORAGE
value: s3
- name: REGISTRY_STORAGE_S3_REGION
value: auto
- name: REGISTRY_STORAGE_S3_REGIONENDPOINT
value: https://.r2.cloudflarestorage.com
- name: REGISTRY_STORAGE_S3_ENCRYPT
value: "false"
- name: REGISTRY_STORAGE_S3_SECURE
value: "true"
- name: REGISTRY_STORAGE_S3_CHUNKSIZE
value: "104857600"
- name: REGISTRY_STORAGE_S3_BUCKET
value:
- name: REGISTRY_STORAGE_S3_ACCESSKEY
valueFrom:
secretKeyRef:
name: r2-secret
key: ACCESS_KEY_ID
- name: REGISTRY_STORAGE_S3_SECRETKEY
valueFrom:
secretKeyRef:
name: r2-secret
key: ACCESS_SECRET_KEY
Once we've modified the deployment file, we apply it.
kubectl apply -f registry-deployment.yaml
Create service and ingress
To access the registry, we might want to create a service and an ingress resource.
The registry exposes at port 5000, so we create a service to that port.
vi registry-service.yaml
apiVersion: v1
kind: Service
metadata:
name: r2-registry
spec:
type: ClusterIP
ports:
- port: 5000
targetPort: 5000
protocol: TCP
selector:
app: r2-registry
And we apply it.
kubectl apply -f registry-service.yaml
Next, we create an ingress resource so we can access the registry using our own domain or subdomain.
vi registry-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: r2-registry
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
rules:
- host: registry.binarycomet.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: r2-registry
port:
number: 5000
And we apply it.
kubectl apply -f registry-ingress.yaml
Next steps
Now we have a working Docker registry that can be accessed via our own domain or subdomain, but it's not production-ready yet.
You should add authentication so only the users authorized can access the registry.
Also, it might be interesting to create an SSL certificate, so we don't have to register it as an insecure-registries
everywhere we want to use it.