This host proxies and caches image pulls from
ghcr.io. Point Docker or containerd here to speed up pulls
of your org's published images and cut outbound rate-limit hits.
Replace mirror.example.com below with this server's actual
hostname.
Most ghcr.io images require auth even for pulls. Generate a personal
access token with the read:packages scope, then log in —
this credential works whether you pull directly from GitHub or through
the mirror.
export CR_PAT=YOUR_TOKEN
echo $CR_PAT | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin
Add this mirror as a registry-mirror in the Docker
daemon config, then restart the daemon.
{
"registry-mirrors": ["https://mirror.example.com"]
}
# apply the config
sudo systemctl daemon-reexec
sudo systemctl restart docker
Since ghcr.io images are always pulled with the full
ghcr.io/... reference, the containerd
hosts.toml approach below is the more reliable per-registry
mirror on most setups.
Open Settings → Docker Engine, merge the same key into the JSON editor there, then click Apply & Restart.
{
"builder": { "gc": { "enabled": true } },
"registry-mirrors": ["https://mirror.example.com"]
}
For containerd nodes — k3s, k8s, bare containerd — configure a mirror specifically for the GHCR namespace:
server = "https://ghcr.io"
[host."https://mirror.example.com"]
capabilities = ["pull", "resolve"]
Restart containerd afterward:
sudo systemctl restart containerd. For private images, put
an imagePullSecret referencing your GitHub PAT on the pod
spec as usual — auth still flows through even when the pull is served
by the mirror.
docker info --format '{{ .RegistryConfig.Mirrors }}'
# pull a ghcr.io image and check it came from the mirror
docker pull ghcr.io/your-org/your-image:latest
curl -s https://mirror.example.com/v2/ -o /dev/null -w "%{http_code}\n"
| Check | Expected result |
|---|---|
docker info | Mirror URL listed under Registry Mirrors |
GET /v2/ | 200 or 401 — mirror is reachable |
| First pull of an image | Slower — cache miss, fetched from upstream and stored |
| Repeat pull of same image | Fast — served from local cache |
ghcr.io.
docker push still goes straight to ghcr.io
— this mirror only accelerates pulls. Image visibility (public vs.
private) and package permissions are enforced by GitHub regardless of
which path the pull takes. If this mirror is served over plain HTTP
internally, add it to insecure-registries instead of
registry-mirrors, or terminate TLS in front of it.