Migrating from Docker Hub to ECR Public Gallery

Self-Introduction
Hi, I'm Tetsu. I joined KTC in March 2025. I worked as an infrastructure engineer handling both on-premises and cloud environments. At KTC, I've joined the team as a platform engineer.
I'm a big fan of travel and nature, so I usually head out somewhere far during long holidays.
Overview
In this article, I’ll walk you through how to update your GitHub Actions workflow to pull public container images—such as JDK, Go, or nginx, from the ECR Public Gallery instead of Docker Hub.
Starting April 1, 2025, Docker Hub will tighten the rules on pulling public container images for unauthenticated users. More specifically, unauthenticated users will be limited to 10 image pulls per hour per source IP address. Learn more here.
The virtual machines that run GitHub Actions workflows are shared across all users, which means Docker Hub sees only a limited set of source IP addresses. Because of this, the above limits became a bottleneck when building containers with GitHub Actions, so we'll need to find a workaround.
Prerequisites
At our company, we used GitHub Actions with the following configuration to automate container builds (this is a roughly abstracted configuration).
Considering Countermeasures
We explored a few ways to deal with the Docker Hub pull limit.
Using a Personal Access Token (PAT) to Log In to Docker Hub and Pull
You might be thinking, "Why not just authenticate with Docker Hub in the first place?" Fair point. You can generate a Docker Hub PAT and use it in your GitHub Actions workflow with docker login to authenticate. That way, you can get around the pull limit.
Just keep in mind, PATs are tied to individual users. Since our team shares GitHub Actions workflows, linking tokens to individual users isn’t ideal from a license management standpoint.
Log in to Docker Hub with your Organization Access Token (OAT) and pull
It's basically the same method as above, but the key difference is that you're authenticating with a shared token tied to your OAT.
To use this shared token, you'll need a Docker Desktop license for either the Team or Business plan.
Migrating to GitHub Container Registry (GHCR)
Here, I'll cover how to pull container images from GitHub Container Registry (GHCR), which is provided by GitHub. By using {{ secrets.GITHUB_TOKEN }} in your GitHub Actions workflow, you can authenticate and pull container images. That said, searching for images can be a bit tricky, especially if you're trying to compare versions with what's available on Docker Hub.
Transition to ECR Public Gallery
Here's how you can pull container images from the ECR Public Gallery provided by AWS. Restrictions differ depending on whether you use IAM to authenticate with ECR Public Gallery, but it's basically free to use.
For unauthenticated users, the following limits apply per source IP address when using the ECR Public Gallery:
- 1 pull per second
- 500GB of pulls per month
On the other hand, authenticated users are subject to the following restrictions on an account-by-account basis.
- 10 pulls per second
- Transfers over 5TB/month are charged at $0.09 per GB (the first 5TB is free)
You can find more details in the official documentation below.
If you are not using an AWS account, data transferred from a public repository is restricted based on the source IP.
The ECR Public Gallery includes official Docker images, which are equivalent to those on Docker Hub. That makes it easier to use in practice and simplifies the migration process.
Case Comparison
I reviewed the proposals above and evaluated them based on QCD. Here's the comparison table:
Proposals | Quality | Cost | Delivery |
---|---|---|---|
Log in to Docker Hub using PAT | × - Relies on personal tokens, which isn't ideal for organizations - No change in convenience from the current setup |
〇 No additional cost | 〇 Easy to implement with less workload |
Log in to Docker Hub using OAT | ○ No change from the current setup | × License costs increase depending on the number of users | × License changes take time to process |
Transition to GHCR | △ Hard to find equivalent images currently used on Docker Hub | 〇 No additional cost | 〇 Easy to implement with less workload |
Transition to ECR Public Gallery | 〇 Easy to find matching currently used on Docker Hub | 〇 No additional cost | 〇 Easy to implement with less workload |
- One advantage of using PAT or OAT is that it keeps things as convenient as they are now.
- GHCR can be easily set up using GitHub's {{ secrets.GITHUB_TOKEN }}, but it's harder to search for container images compared to ECR Public Gallery.
- ECR Public Gallery requires some IAM policy changes, but since they're minor, the extra workload is minimal.
Based on these points, we decided to go with the plan of "migrating to ECR Public Gallery," as it's low-workload, cost-free, and offers good usability.
Note: Depending on your environment or organization, this option may not always be the best fit.
Settings for Migrating to ECR Public Gallery
To migrate, you'll need to update the container image source, set up the YAML file for the GitHub Actions workflow, and configure AWS accordingly.
Diagram
Fixing the Container Image Source
Searching for Container Images
In most cases, you probably define where to pull container images from in files like your Dockerfile or docker-compose.yml. This time, we'll walk through how to migrate the source of a JDK container image from Docker Hub to ECR Public Gallery using a Dockerfile.
Let's say your Dockerfile includes a FROM clause like this:
FROM eclipse-temurin:17.0.12_7-jdk-alpine
Search here to check if the image is available on ECR Public Gallery. In this case, search for the official Docker Hub image like eclipse-temurin
before the ":" and pick the one labeled "by Docker."
Select "image tags" to display the image list.
Type the tag of the official Docker Hub image (in this case, 17.0.12_7-jdk-alpine
) into the image tags search field to find the image you're looking for. Then copy the "Image URI".
Fixing the Container Image Source
Paste the modified container image URI into the FROM line.
In this case, the updated URI looks like the example below (note the addition of public.ecr.aws/docker/library/ compared to the original).
FROM public.ecr.aws/docker/library/eclipse-temurin:17.0.12_7-jdk-alpine
With this change, your setup will now pull images from ECR Public Gallery.
AWS Configuration
To pull from ECR Public Gallery while authenticated, you'll need to set up an IAM role and policy.
IAM Role
You can follow the steps in GitHub's official documentation for this.
Start by setting up the identity provider, then create the IAM role.
IAM Policy
Create an IAM policy that allows the action to pull from the ECR Public Gallery. I referred to the following docs for this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetAuthorizationToken",
"Effect": "Allow",
"Action": [
"ecr-public:GetAuthorizationToken",
"sts:GetServiceBearerToken"
],
"Resource": "*"
}
]
}
Attach this IAM policy to the IAM role you created above.
Added Login Process to ECR Public Gallery in Github Actions
To log in to the ECR Public Gallery with authentication, add a login process to the YAML file that defines the Github Actions workflow.
In our setup, we add the following before the Docker Build step.
## ECR Public Galleryへログイン
- name: Login to ECR Public Gallery
id: login-ecr-public
run: |
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
*Since the ECR Public Gallery is located in the us-east-1 region, make sure to explicitly set --region us-east-1
.
Conclusion
In this article, we walked through how to set up your GitHub Actions workflow to pull public container images (like JDK, Go, nginx, etc.) from the ECR Public Gallery instead of Docker Hub.
Hope this helps with your development and daily tasks!
関連記事 | Related Posts
We are hiring!
【DBRE】DBRE G/東京・名古屋・大阪・福岡
DBREグループについてKINTO テクノロジーズにおける DBRE は横断組織です。自分たちのアウトプットがビジネスに反映されることによって価値提供されます。
【クラウドエンジニア】Cloud Infrastructure G/東京・大阪・福岡
KINTO Tech BlogWantedlyストーリーCloud InfrastructureグループについてAWSを主としたクラウドインフラの設計、構築、運用を主に担当しています。