How to Build a Fast Docker Registry Proxy in China with Kubernetes and Envoy
This guide shows how to set up a self‑hosted Docker registry proxy using Docker's registry image, Kubernetes (k3s), and Envoy to accelerate access to public image repositories like gcr.io, quay.io, and Docker Hub from within China, covering prerequisites, custom Dockerfile, deployment manifests, Envoy configuration, authentication, and cache cleanup.
When using Docker and Kubernetes in China, access to public registries such as gcr.io and quay.io is blocked, leaving only the slow Docker Hub. This article explains how to build a local registry proxy that caches these images.
1. Prerequisites
A server that can reach the upstream registries (e.g., gcr.io)
A domain name and SSL certificate (Let’s Encrypt is sufficient)
2. Core Idea
The Docker registry project can act as a pull‑through cache. By setting the remoteurl parameter, the private registry forwards requests to the upstream registry and caches the layers locally.
3. Custom Registry
Create a Dockerfile that extends the official registry image and adds an entrypoint script to inject environment variables into the configuration.
FROM registry:2.6
LABEL maintainer="registry-proxy Docker Maintainers https://fuckcloudnative.io"
ENV PROXY_REMOTE_URL=""
ENV DELETE_ENABLED=""
COPY entrypoint.sh /entrypoint.shThe entrypoint.sh script writes the proxy settings, CORS headers, and optional delete configuration into /etc/docker/registry/config.yml before launching the registry.
#!/bin/sh
set -e
CONFIG_YML=/etc/docker/registry/config.yml
if [ -n "$PROXY_REMOTE_URL" -a `grep -c "$PROXY_REMOTE_URL" $CONFIG_YML` -eq 0 ]; then
echo "proxy:" >> $CONFIG_YML
echo " remoteurl: $PROXY_REMOTE_URL" >> $CONFIG_YML
echo " username: $PROXY_USERNAME" >> $CONFIG_YML
echo " password: $PROXY_PASSWORD" >> $CONFIG_YML
echo "------ Enabled proxy to remote: $PROXY_REMOTE_URL ------"
elif [ $DELETE_ENABLED = true -a `grep -c "delete:" $CONFIG_YML` -eq 0 ]; then
sed -i '/rootdirectory/a\ delete:' $CONFIG_YML
sed -i '/delete/a\ enabled: true' $CONFIG_YML
echo "------ Enabled local storage delete -----"
fi
sed -i "/headers/a\ Access-Control-Allow-Origin: ['*']" $CONFIG_YML
sed -i "/headers/a\ Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']" $CONFIG_YML
sed -i "/headers/a\ Access-Control-Expose-Headers: ['Docker-Content-Digest']" $CONFIG_YML
case "$1" in
*.yaml|*.yml) set -- registry serve "$@" ;;
serve|garbage-collect|help|-*) set -- registry "$@" ;;
esac
exec "$@"4. Deploy the Cache Service
Build the image and run it, or use the pre‑built image yangchuansheng/registry-proxy. Deploy it in a k3s cluster with a Deployment and Service manifest (example shown for docker.io).
apiVersion: apps/v1
kind: Deployment
metadata:
name: dockerhub
labels:
app: dockerhub
spec:
replicas: 1
selector:
matchLabels:
app: dockerhub
template:
metadata:
labels:
app: dockerhub
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 8.8.8.8
- 8.8.4.4
containers:
- name: dockerhub
image: yangchuansheng/registry-proxy:latest
env:
- name: PROXY_REMOTE_URL
value: "https://registry-1.docker.io"
- name: PROXY_USERNAME
value: "yangchuansheng"
- name: PROXY_PASSWORD
value: "********"
ports:
- containerPort: 5000
protocol: TCP
volumeMounts:
- mountPath: /etc/localtime
name: localtime
- mountPath: /var/lib/registry
name: registry
volumes:
- name: localtime
hostPath:
path: /etc/localtime
- name: registry
hostPath:
path: /var/lib/registry
---
apiVersion: v1
kind: Service
metadata:
name: dockerhub
labels:
app: dockerhub
spec:
selector:
app: dockerhub
ports:
- protocol: TCP
name: http
port: 5000
targetPort: 50005. Proxy Selection
If you only cache docker.io, you can expose the proxy on port 443 and add SSL. For multiple registries, use an edge proxy (Ingress) that routes by domain name. Envoy is recommended for its dynamic configuration API.
6. Envoy Configuration
Deploy Envoy as a Deployment with two replicas, exposing ports 80 and 443. Mount the configuration files via hostPath and edit envoy.yaml, lds.yaml, and cds.yaml to define listeners, routes, and clusters for each upstream registry.
# envoy.yaml (snippet)
node:
id: node0
cluster: cluster0
dynamic_resources:
lds_config:
path: /etc/envoy/lds.yaml
cds_config:
path: /etc/envoy/cds.yaml
admin:
access_log_path: "/dev/stdout"
address:
socket_address:
address: "0.0.0.0"
port_value: 150017. Verify Acceleration
Pull an image through the proxy, e.g.:
docker pull docker.fuckcloudnative.io/library/nginx:alpineThe pull completes quickly, confirming the cache works.
8. Cache All Registries
Repeat the Deployment and Envoy configuration for other registries ( gcr.io, k8s.gcr.io, quay.io, ghcr.io) by adjusting PROXY_REMOTE_URL and adding corresponding virtual hosts and clusters in Envoy.
9. Runtime Configuration
Configure Docker, containerd, or Podman to use the proxy as a registry mirror. Example for Docker ( /etc/docker/daemon.json):
{
"registry-mirrors": ["https://docker.fuckcloudnative.io"]
}For containerd ( /etc/containerd/config.toml) and Podman ( /etc/containers/registries.conf) similar mirror entries are added.
10. Clean Up Cache
Deploy a separate registry with the delete feature enabled to remove old layers, or schedule a cron job that periodically deletes /var/lib/registry/*. A UI such as joxit/docker-registry-ui can be added for manual cleanup.
11. Authentication
Protect the proxy with basic auth using an htpasswd file stored in a Kubernetes Secret. Add the following environment variables to the Deployment:
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"Mount the secret as a volume at /auth. Users must log in with docker login docker.fuckcloudnative.io before pulling images.
12. Optional Token Authentication
For finer‑grained access control, integrate a token authentication server such as docker_auth.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
