DockerHubのpull制限が厳しくなるのでECR Public Galleryへ移行しました

# 概要

弊社のDocker環境では、ベースイメージの多くをDockerHubから取得しています。
しかし、2025年4月1日から認証なしのユーザーdocker pullの制限が厳しくなります。

そのため、別のレジストリサービスを検討・乗り換えしました。
その調査内容をまとめます。

# DockerHubのレートリミットの事情

DockerHubのレートリミットは、2025年4月1日から以下の通りとなります。

[Docker Hub pull usage and limits](https://docs.docker.com/docker-hub/usage/pulls/)

> 2025年4月1日より、Pro、Team、またはBusinessのサブスクリプションを持つすべてのユーザは、公正な使用によるDocker Hubのプルが無制限になります。認証されていないユーザーと無料のPersonalアカウントを持つユーザーは、以下のプル制限があります：
>
> 認証されていないユーザー： 10プル/時間
無料アカウントの認証済みユーザー： 100プル/時間

# 要件

public imageのpullをレートリミットを気にせず実施すること。


# 結論

AWS ECR Public Galleryを認証付きで使用することとしました。

https://gallery.ecr.aws/

理由は、以下の3つです。
- イメージを検索しやすい
- 使用したい公式イメージが配布されている
- レートリミットが緩い

# GitHub ActionsはDockerHubのレートリミットの影響を受けない説

調査の中で、「**GitHub Actions環境からのパブリックイメージpullは、レートリミットの影響を受けないようDockerHubと協力している**」という情報を発見しました。ただし、これは2020年時点の情報です。

> For publicly accessible containers we are working with docker hub to make sure you will not be impacted by the new rate limits. If you need private containers we still do not have a solution for that problem for forks of public repos.

https://github.com/actions/runner-images/issues/1445#issuecomment-713861495

また、すべての共有パブリックランナーは、DockerHubのレート制限が非常に高い共有アカウントで自動的にDockerHubにログインしているようです。
これが上述したレートリミットの影響を受けない理由かもしれません。

> All of the shared public runners are automatically logged in to docker hub with a shared account that has significantly higher rate limits on Docker Hub. I just ran a job that pulled that image and was not able to reproduce the issue.

https://github.com/actions/runner-images/issues/1445#issuecomment-2332090826


一方で、「2024年4月時点では、Arm64とGPUランナーではレートリミットに関する例外から除外されておりpull回数制限に引っかかる場合がある」ようです。

> Sharing part of the response I got from GitHub Support:
>
> [...] certain groups of runners are currently excluded from the rate limiting exception - most notably Arm64 and GPU runners.
>
> This is obviously disappointing, but at least we can work around it for now.

https://github.com/actions/runner-images/issues/1445#issuecomment-2208581589


# 認証なしの場合、どのようにレートリミットをかけているのか

IPごとにかけています。

>  匿名ユーザーの場合、プル率の制限は 1 つの IP アドレスにつき、6 時間ごとに 100 プルに設定されています。

https://matsuand.github.io/docs.docker.jp.onthefly/docker-hub/download-rate-limit/

> AWS アカウントを利用していない場合、パブリックリポジトリから転送されるデータはソース IP によって制限されます。

https://aws.amazon.com/jp/ecr/pricing/

# Github Actions環境のIPアドレス範囲は？

非常に広いIP範囲ですが、それらのIPは共有されているため他人がすでに制限に達するだけdocker pullしている場合、そのIPが割り当てられた場合はpullが失敗すると思われます。

https://docs.github.com/ja/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#ip-addresses


Github Actionsで使用されるIPアドレス範囲は、以下のように調べることができます。

https://docs.github.com/ja/rest/meta/meta?apiVersion=2022-11-28#get-github-meta-information

```
$ curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <YOUR-TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/meta
```


# 検討対象

乗り換え先としてGitHub Container RegistryとAWS ECR Public Galleryを比較します。

## 比較

|  | AWS ECR | ghcr.io |
| --- | --- | --- |
| 新規アカウントや認証の必要性 | [publicイメージのpullは無料（500GB制限あり）](https://aws.amazon.com/jp/ecr/pricing/) | publicイメージのpullには不要、[その他イメージや操作には必要](https://docs.github.com/ja/packages/working-with-a-github-packages-registry/working-with-the-container-registry?utm_source=chatgpt.com#container-registry%E3%81%A7%E3%81%AE%E8%AA%8D%E8%A8%BC) |
| 料金 | 500GB（認証ありで5TB）のpullまで無料 | [publicイメージは無料、privateイメージは有料](https://docs.github.com/ja/billing/managing-billing-for-your-products/managing-billing-for-github-packages/about-billing-for-github-packages#github-packages-%E3%81%AE%E8%AA%B2%E9%87%91%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6) |
| pullのレートリミット | [1回/秒（認証なし）、10回/秒（認証あり）](https://docs.aws.amazon.com/ja_jp/general/latest/gr/ecr-public.html#:~:text=Rate%20of%20authenticated%20image%20pulls,unauthenticated%20image%20pulls%20per%20second) | publicイメージについてはおそらくなし |


## GitHub Container Registry

### 料金

publicイメージは無料。privateイメージは有料になります。

> GitHub Container Registryで匿名アクセスが可能になり、私たち自身のスーパーリンターのパブリックイメージを公開することで、物事を始めることができました。 GitHub Container Registryは、公開イメージは無料です。 Container Registry は、ベータ期間中はプライベートイメージが無料ですが、GitHub Packages の一部として一般提供される際には、同じ価格モデルに従う予定です。
>
> **GitHub Container Registry is free for public images**. Container Registry is free for private images during the beta, and as part of GitHub Packages will follow the same pricing model when generally available.

https://github.blog/news-insights/product-news/introducing-github-container-registry/

**privateイメージの無料枠**

| プラン | ストレージ | データ転送量 |
| --- | --- | --- |
| Free | 500MB | 1GB |
| Pro | 2GB | 10GB |
| Team | 2GB | 10GB |
| Enterprise Cloud | 50GB | 100GB |

無料枠を超えると、ストレージとデータ転送量はそれぞれ以下の料金がかかります。

- ストレージ：$0.25/GB
- データ転送量：$0.50/GB

### レートリミット

公式ドキュメントには、publicイメージは無料と記載がありますが、ghcrについてのレートリミットの明確な表記は見当たりませんでした。
少なくともpublicイメージに関してはrate limitがないという意見が多いです。

> ghcr.ioは（GitHubのメインプロダクトではありませんが）レート制限を全く課しておらず、これは持続可能であることの証明だと言えるでしょう

https://news.ycombinator.com/item?id=43125089#:~:text=with%20such%20a%20small%20rate,good%20luck

> 公的レジストリの利用率制限はないようだ（ただし、これを変更する意図があるかどうかは不明）。

https://github.com/orgs/community/discussions/49671

> GHCRには、パブリック画像に対するそのような制限はありません。

https://x.com/alexellisuk/status/1561275855153909760

### 検索性

検索しにくいです...
**ghcr.io**で検索しても、https://github.com/features/actions にリダイレクトされます。
確認できた範囲ではイメージ名での検索ページがあるわけではなく、各リポジトリに行きpackageタブを確認しなくてはいけませんでした。

いい検索方法があれば教えてください...

![スクリーンショット 2025-03-11 10.27.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/959ef852-c688-43d7-9cae-43b6a8e9204f.png)


## AWS ECR Public Gallery

### 料金

アカウントを使用しない場合、500GB制限を上限に使えなくなりますが、課金は発生しません。
アカウントによる認証ありの場合、5TBを超えた場合は0.09 USD/GB課金されますが、現状の使い方では超えることはほぼあり得ないと考えられました。

### レートリミット

**public image pull**

認証なしでは1秒あたり1回（固定）、認証ありなら10回（引き上げ可能）。

**容量制限**

認証なしでは月あたり500GB（固定）、認証ありなら5TB（引き上げ可能）。

例えばalpineのイメージは約4MBのため、認証なしでも500GB/月 ÷ 0.004GB ÷ 30日 = 4166回/月 のpullが可能です。ただしGithub ActionsのIP共有に注意が必要です。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/ecr-public.html#:~:text=Rate%20of%20authenticated%20image%20pulls,unauthenticated%20image%20pulls%20per%20second


### 検索性

検索はしやすいです。画像のように、キーワード検索が可能です。

![スクリーンショット 2025-03-11 10.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/560242f3-a4f8-48bd-942e-6e5fd5460ac2.png)


# 認証すべきか

認証すべきだと思います。

理由としては、Github ActionsによるIP共有の影響を受けないためです。
AWS ECR Public Galleryには認証なしの場合IPごとに500G/月とは別に、1回/秒のpull制限があります。
これに引っかかることが時々あるようです。

認証することで制限が10回/秒に緩和されます。

https://www.codingfeline.com/2023/07/28/github-actions-public-ecr-toomanyrequests/

認証した場合でも、DockerHubよりもECRの方が有利です。

|  | アカウント認証あり | 非認証 | 有償アカウント認証（docker） |
| --- | --- | --- | --- |
| docker | 100 pull/h | IPごと10 pull/h | なし |
| ECR | 無料枠5 TB/月 | IPごと500 GB/月 <br> alpine（約4MB）の場合、173 pull/hの計算 |

# 認証の方法（ECR）

https://docs.aws.amazon.com/cli/latest/reference/ecr-public/get-login-password.html

```
$ aws ecr-public get-login-password \
    --region us-east-1
| docker login \
    --username AWS \
    --password-stdin public.ecr.aws
```

※東京リージョンは対応しておらずエラーとなります。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/ecr-public.html

```
Could not connect to the endpoint URL: "https://api.ecr-public.ap-northeast-1.amazonaws.com/"
Error: Cannot perform an interactive login from a non TTY device
```