The problem
Ten machines pulling the same 40 GB model is forty times the bandwidth and none of the benefit.
Every node re-downloads the same weights. Every CI runner re-pulls the same base image. The bytes are identical, the uplink is not free, and the second machine waits exactly as long as the first.
One fetch, shared live
Concurrent requests for the same file share a single upstream download — later arrivals stream from the partial file as it lands rather than queueing behind it.
Local disk speed
A cached hit is served off local storage. No round trip, no rate limit, no dependency on anyone else's uptime.
Nothing to rewrite
Point an environment variable at the cache, or prefix an image name. Your training scripts and Dockerfiles stay as they are.
Containers
Put the registry in the path. The reference says where it came from, so adding a registry needs no change here and no daemon configuration on your side.
# instead of docker.io/library/redis:7
docker pull cache.example.com/docker.io/library/redis:7
# any registry, same shape
docker pull cache.example.com/ghcr.io/your-org/api:v2
docker pull cache.example.com/quay.io/prometheus/busybox:latest
Models and datasets
One environment variable. Metadata is proxied; file bytes are intercepted and cached, so the second machine to want a checkpoint reads it off local disk.
# unchanged code, now served from cache
export HF_ENDPOINT=https://cache.example.com
python -c "from huggingface_hub import snapshot_download;
snapshot_download('meta-llama/Llama-3.1-8B')"
Built for the boring parts
Integrity, not optimism
Container blobs are digest-verified before they are kept. Corrupt bytes are discarded rather than cached and served forever.
Eviction that knows better
Least-recently-used, except for repositories deleted upstream — evicting a live one costs a re-download, evicting a vanished one destroys the last copy.
Per-key authorisation
Credentials are keys with rules. A key can be allowed to pull one registry and nothing else, and revoking it takes effect on the next request.
Runs where your data is
A single container with a volume. No control plane, no external dependencies, no phone-home.
Your credentials
Sign in to create and revoke the keys you use against this cache. Nobody needs shell access on the cache to rotate one.
What it is not
A cache is shared storage, not a security boundary. Everyone whose key permits a path is served whatever is cached there — Muninn does not re-check entitlement with the upstream registry on a hit, because on a hit it never contacts the upstream at all. If two tenants must not read each other's private images, give them separate caches.
It is also not a mirror. Nothing is pre-populated and nothing is guaranteed to still be here; it holds what has been asked for, and evicts under pressure.