Last reviewed: 2026-11-10
Docker Hub Image Caching
Background
Docker Hub enforces rate limits on image pulls, counted per IP address for anonymous pulls.
In shared Kubernetes environments, these limits can be quickly exceeded, causing:
- Failed pod deployments (ImagePullBackOff errors)
- Service disruptions during scaling events
- Deployment delays
- HTTP 429 “Too Many Requests” errors
To prevent these issues, we’ve implemented an automatic caching solution that stores Docker Hub images in our own AWS ECR registry.
How It Works
To use the ECR cache for your Docker Hub images, you need to update your deployment manifests or Dockerfiles to point to the cache:
- Update your image reference to use the ECR cache URL
- Deploy the updated manifest to your cluster
- The image is pulled through ECR, which caches it from Docker Hub on first use
- Subsequent pulls are served from the cache, avoiding Docker Hub rate limits
Image Path Mapping
The path structure depends on the image type:
Official Docker Hub images (nginx, redis, postgres, etc.) require the /library/ prefix:
# Original
image: nginx:latest
# ECR cache path
image: 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/library/nginx:latest
User or organization images (no /library/ prefix):
# Original
image: grafana/grafana:latest
# ECR cache path
image: 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/grafana/grafana:latest
Examples
Official image (nginx):
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/library/nginx:latest
Organization image (Grafana):
apiVersion: apps/v1
kind: Deployment
metadata:
name: monitoring
spec:
template:
spec:
containers:
- name: grafana
image: 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/grafana/grafana:latest
Using the Cache in Docker Builds
Base images in your Dockerfile can also be pulled through the cache when you build in GitHub Actions. Update the FROM line the same way as an image reference:
# Original
FROM node:22
# ECR cache path
FROM 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/library/node:22
With build-and-push-ecr
build-and-push-ecr logs in to ECR before it builds, so no extra steps are needed:
jobs:
build:
runs-on: ubuntu-24.04
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: jppol-idp/build-and-push-ecr@main
with:
namespace: <your-namespace>
image_name: my-app
image_tag: $
If you build the image yourself
If you run docker build in your own step (e.g. with tag-and-push-ecr, or build-and-push-ecr with run_build: false), log in to ECR before the build:
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::354918371398:role/github-access-<your-namespace>
aws-region: eu-west-1
- uses: aws-actions/amazon-ecr-login@v2
with:
registries: "354918371398"
- run: docker build . -t local-build
- uses: jppol-idp/tag-and-push-ecr@main
with:
source_tag: local-build
namespace: <your-namespace>
image_name: my-app
image_tags: $
The job needs id-token: write permission to assume the role.
Supported Images
The cache works for all Docker Hub images, once the image reference points to the ECR cache path:
| Image Type | Example | ECR cache path |
|---|---|---|
| Official images | nginx:latest | docker-hub/library/nginx:latest |
| Official with docker.io | docker.io/nginx:latest | docker-hub/library/nginx:latest |
| User/organization images | grafana/grafana:latest | docker-hub/grafana/grafana:latest |
| User/organization with docker.io | docker.io/grafana/grafana:latest | docker-hub/grafana/grafana:latest |
Images from other registries cannot be pulled through this cache:
public.ecr.aws/owner/image- Amazon ECR Publicgcr.io/project/image- Google Container Registryquay.io/organization/image- Quay.ioghcr.io/owner/image- GitHub Container Registry- Images already in ECR
Benefits
- No rate limiting: Eliminates Docker Hub 429 errors
- Faster deployments: Images are pulled from ECR in the same AWS region
- Improved reliability: Reduces dependency on Docker Hub availability
- ArgoCD compatible: Syncs correctly with GitOps workflows
Troubleshooting
My pod shows ImagePullBackOff
Check the pod events to see the specific error:
kubectl describe pod <pod-name> -n <namespace>
If the error mentions ECR authentication or “not found”, check that the image path follows the mapping above (official images need /library/). If it still fails, write to the IDP team in your team’s onboarding channel on Slack.
My build fails pulling the base image
If docker build fails with “no basic auth credentials” or “denied”, the runner is not logged in to ECR when the build starts. Use build-and-push-ecr, or add the login steps from If you build the image yourself before your build. If it still fails, write to the IDP team in your team’s onboarding channel on Slack.
I want to verify my image is cached
You can check the actual image being used:
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[*].image}'
This should show an ECR URL starting with 354918371398.dkr.ecr.eu-west-1.amazonaws.com/docker-hub/.
Additional Information
For questions or issues, write to the IDP team in your team’s onboarding channel on Slack.