ECR helps — but it doesn’t solve everything

In this article, I want to show a real problem we faced and how we solved it in a simple way.

When your system builds container images, you typically pull base images directly from Docker Hub. For small projects, this works fine. But for enterprise-grade systems running many builds, Docker Hub’s rate limits quickly become a bottleneck that can break your entire CI/CD pipeline.

We faced this exact problem. Here’s how we solved it—and how you can too.

The Problem

Here are the main challenges:

1. Docker Hub Rate Limits

Docker Hub has strict limits: 100 pulls every 6 hours (without login) and 200 pulls every 6 hours (with login). If you run many builds, you will hit this limit quickly. When that happens, your builds fail with errors like: 429 Too Many Requests

2. Multiple Environments More Problems

If you have dev, stage, and prod environments, you need to make sure all of them use the same image versions. Updating base images across all environments becomes messy and hard to control.

3. Slow Image Pulls

Pulling images from the internet is slower than pulling from inside AWS. In CI/CD, speed matters.

Common Solutions (and Why They’re Not Perfect)

1. Central ECR Repository

You can store images in a central AWS account and pull from there. Sounds good, but: You need to manually pull from Docker Hub and push to ECR, multi-architecture images (ARM vs AMD) can cause issues, and it doesn’t scale well.

2. Automating Sync

You can automate pulling and pushing images. But: It adds operational overhead, more scripts, more maintenance, and more things that can break.

So… is there a simpler way?

The Simple Solution: Use ECR as a Cache

AWS provides ECR pull-through cache. In simple terms, it acts like a middle layer between your builds and Docker Hub. Instead of pulling directly from Docker Hub, your builds pull from ECR.

How It Works

Here’s what happens: Your build requests an image, ECR checks if it already has it, if yes it returns it instantly, if not it downloads it from Docker Hub, it stores (caches) the image, and next time it serves it from cache. After the first pull, Docker Hub is no longer involved for that image.

Why This Is Useful

1. No More Rate Limits

Once cached, your builds stop hitting Docker Hub. That means: No more failed builds and no more waiting.

2. Faster Builds

Images are pulled from AWS (same region), which is much faster. In many cases, builds are 30–50% faster.

3. Lower Costs

You reduce: External traffic and Docker Hub usage.

4. One Central Place

All environments (dev, stage, prod) use the same cached images. This makes things: consistent and easier to manage.

Want to See a Real Example?

I’ve created a full working example using AWS CDK, where everything is set up step by step. Check it out here: aws-ecr-pullthrough-cache-cdk

Using the Cache in Your Builds

Once configured, update your Dockerfile or build configuration to use the cache:

1
2
3
4
5
# Instead of:
FROM php:8.3-fpm

# Use:
FROM 123456789012.dkr.ecr.us-east-1.amazonaws.com/docker-hub/php:8.3-fpm

For CodeBuild or other CI/CD tools, configure the registry URL in your build environment.

Final Thoughts

If your builds are failing because of Docker Hub limits, this is one of the easiest fixes. With ECR pull-through cache, you get: stable builds, faster performance, and lower costs, all with minimal changes.

The setup takes minutes, but the impact is immediate. Start with Docker Hub, then add other registries (GitHub Container Registry, Quay, etc.) as needed. Your CI/CD pipeline will thank you.