On this page
What Is a Container Registry (and How Do Rate Limits Work)?
A container registry stores and serves your Docker images. Learn how registries work, why pulls fail with rate limits, and how to avoid them.
Quick answer
- A container registry is a service that stores container images and serves them when builds and deploys pull them.
- Public registries (Docker Hub) enforce pull rate limits, which can suddenly fail your CI or deploys.
- The fix: use an authenticated pull, or mirror images to a private registry (GHCR, ECR, your own) and pull from there.
What does a container registry do?
A registry stores images — the layered, tagged bundles your Dockerfile produces — and serves them on demand. When you run docker pull nginx, you’re fetching from Docker Hub. When CI builds your app, it pulls base images; when a server deploys, it pulls your app image. The registry is the middleman in every container workflow, and it’s why ‘works on my machine’ meets ‘pull failed’ on another machine: the machine needs to reach the registry and have permission.
Why do rate limits break builds and deploys?
Docker Hub limits anonymous pulls per IP address (and authenticated pulls per account) — typically 100 anonymous pulls per 6 hours. A shared office IP, a CI runner pool, or a cluster of servers all counting as one IP can exhaust the quota, and suddenly every pull fails with ‘toomanyrequests: You have reached your pull rate limit’. The failure is invisible in your code — nothing changed, yet builds and deploys start failing. Other registries have their own limits, and all of them get tighter the more you rely on them.
How do I avoid pull rate limits?
Three options, in order of preference. Authenticate: docker login with a free Docker Hub account raises the limit and separates your pulls from anonymous traffic. Mirror: copy the base images you depend on into your private registry (GHCR, ECR, or a self-hosted one) and change your Dockerfiles to pull from there — this also pins exact versions, which is good supply-chain hygiene. Or run a pull-through cache locally (registry mirror) so each base image is fetched once and served to everything else.
# Authenticate once; pulls from CI and servers count against your account, not anonymous
# (set DOCKER_USERNAME / DOCKER_PASSWORD in CI secrets)
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
# Or mirror a base image to your private registry and pull from there
FROM ghcr.io/your-org/python:3.13-slim # instead of python:3.13-slimWhere this bites vibecoders
The vibecoder’s CI starts failing with a rate-limit error no code change explains — because the assistant’s pipeline pulls base images anonymously from Docker Hub, and a shared runner IP blew the quota. The assistant rarely mentions registry auth or mirrors, since its mental model ends at ‘docker pull works’. One login in CI secrets, or a mirror step, removes the whole failure class.
Where AI coding assistants get this wrong
- Pulling base images anonymously from Docker Hub in CI, hitting anonymous IP limits.
- No version pinning on base images, so builds drift and rate limits hit on every unpinned tag.
- Suggesting a bigger VM when the real fix is registry auth or a mirror.
- Not authenticating in the deploy environment, so prod pulls count against a shared IP.
Checklist
- Authenticate registry pulls in CI and deploy environments.
- Pin base image versions; pull from your private registry or a mirror.
- Know your registry’s pull limits and your actual pull volume.
- Monitor for rate-limit errors (toomanyrequests) so they never hit silently.
FAQ
Is Docker Hub the only registry?
No. GitHub Container Registry (GHCR), AWS ECR, Google Artifact Registry, and self-hosted options like Harbor are common alternatives. Many are free for private images and don’t share Docker Hub’s anonymous limits, which is why teams mirror images there.
How many pulls does my app actually do?
Every build pulls its base images and every deploy pulls your app image — count builds plus deploys times the layers you don’t already have cached. If you’re deploying a handful of times a day from one server, anonymous limits rarely bite; CI with many parallel builds is where they do.
Related topics
- What Is a Software Supply Chain Attack?
- How to Write a Secure Dockerfile
- What Is CI/CD?
- How to Set Up a CI/CD Pipeline With GitHub Actions
- Why Does My App Ignore SIGTERM (and How Do I Fix It)?