This error occurs when you exceed Docker Hub's rate limits for image pulls. Fix it by authenticating to increase limits, using registry mirrors, or upgrading to a Docker paid subscription.
The "toomanyrequests: You have reached your pull rate limit" error means you've exceeded Docker Hub's rate limiting policy for image pulls. Docker Hub limits anonymous pulls to 100 per 6 hours per IP address, and authenticated free users to 200 per 6 hours. In Kubernetes environments, this error frequently occurs because multiple pods across many nodes share the same egress IP address, rapidly consuming the rate limit. CI/CD pipelines and auto-scaling workloads are particularly susceptible since they pull images frequently during deployments and scaling events. The error manifests as HTTP 429 (Too Many Requests) and causes pods to enter ImagePullBackOff state until the rate limit window resets.
Authenticating increases your limit from 100 to 200 pulls per 6 hours:
# Login locally
docker login
# Check remaining pulls
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/ubuntu:pull" | jq -r .token)
curl --head -H "Authorization: Bearer $TOKEN" \
https://registry-1.docker.io/v2/library/ubuntu/manifests/latest 2>&1 | grep -i ratelimitExpected output shows your limits:
RateLimit-Limit: 200
RateLimit-Remaining: 195Add Docker Hub credentials to your cluster:
# Create docker-registry secret
kubectl create secret docker-registry dockerhub-secret \
--docker-server=docker.io \
--docker-username=<YOUR_USERNAME> \
--docker-password=<YOUR_ACCESS_TOKEN> \
--docker-email=<YOUR_EMAIL>
# Patch default ServiceAccount
kubectl patch serviceaccount default -p \
'{"imagePullSecrets": [{"name": "dockerhub-secret"}]}'Apply to deployment:
spec:
template:
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: app
image: myrepo/myapp:latestNote: Create a Docker access token at hub.docker.com/settings/security—don't use your password.
For unlimited pulls, upgrade your Docker subscription:
- Docker Pro: $9/month per user → unlimited pulls
- Docker Team: $15/month per user → unlimited pulls + team management
- Docker Business: Custom pricing → enterprise features
After upgrading:
# Re-authenticate to apply new limits
docker logout && docker login
# Verify unlimited status
curl -s "https://hub.docker.com/v2/users/<USERNAME>" | jq '.is_paid'Check your account at hub.docker.com/settings/billing.
Deploy a local caching proxy to pull once, serve many times:
# Run official pull-through cache
docker run -d \
-p 5000:5000 \
-e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
--name registry-proxy \
registry:2
# Configure Docker daemon to use mirror
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["http://localhost:5000"]
}
EOF
# Reload Docker
systemctl reload dockerAlternative: Use Google's free mirror for popular images:
docker pull mirror.gcr.io/library/ubuntu:latest
docker pull mirror.gcr.io/library/nginx:alpineDistribute pulls across multiple accounts:
# GitHub Actions example
name: Build
on: push
jobs:
build-1:
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USER_1 }}
password: ${{ secrets.DOCKERHUB_TOKEN_1 }}
- run: docker build . -t myapp:v1
build-2:
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USER_2 }}
password: ${{ secrets.DOCKERHUB_TOKEN_2 }}
- run: docker build . -t myapp:v2This spreads 200 pulls × N accounts across your pipeline.
Minimize image pull frequency:
# Pin specific versions (better caching)
FROM ubuntu:22.04
# NOT this (always re-pulls):
FROM ubuntu:latestUse Docker layer caching in CI:
# GitHub Actions with layer caching
- uses: docker/build-push-action@v4
with:
context: .
cache-from: type=registry,ref=myregistry/myapp:buildcache
cache-to: type=registry,ref=myregistry/myapp:buildcache,mode=maxConsider moving base images to your own registry (ECR, GCR, ACR) where you control rate limits.
Current Docker Hub Rate Limits (2025):
- Anonymous: 100 pulls/6 hours per IP
- Free authenticated: 200 pulls/6 hours per account
- Docker Pro/Team/Business: Unlimited (fair use policy)
Enterprise Registry Mirrors:
- Nexus Repository (free/OSS): Proxy all registries with 10GB+ caching
- JFrog Artifactory: Multi-region federation, pull-through cache
- Harbor (free/OSS): Air-gapped registries, image scanning, RBAC
Monitoring Rate Limits: Use regctl to check remaining pulls without consuming quota:
regctl image ratelimit nginx:latestKubernetes Node-Level Authentication: Configure containerd to authenticate at the node level in /etc/containerd/config.toml, avoiding per-pod secrets.
Shared IP Consideration: In cloud environments, all pods may share a NAT gateway IP. A single 100-pod deployment can exhaust anonymous limits instantly.
Failed to connect to server: connection refused (HTTP/2)
How to fix "HTTP/2 connection refused" error in Kubernetes
missing request for cpu in container
How to fix "missing request for cpu in container" in Kubernetes HPA
error: invalid configuration
How to fix "error: invalid configuration" in Kubernetes
etcdserver: cluster ID mismatch
How to fix "etcdserver: cluster ID mismatch" in Kubernetes
running with swap on is not supported
How to fix "running with swap on is not supported" in kubeadm