GitHub Container “R”egistryではなくGitHub Container “r”egistry が正しいと信じているのですが、誰か正解を知っている人がいたら教えて下さい。最初のブログ ではGitHub Container Registry と書いていましたが、その後はGitHub Container registryになりドキュメントでもContainer registryになっているので、やはりContainer registryなのかなと思ってますが、これが気になりすぎてGHCRについて触れるのがいつも憚られています。
Docker Hubのレート制限について
2025年4月1日からDocker Hubの制限がいよいよ厳しくなり、未認証ユーザは1時間で10回しかpullできないようになります。
元々はこれらの変更は2025年3月1日から適用される予定で、しかも認証ユーザでも1時間で40回制限だったのですが、さすがに急すぎて厳しいという声があったのか4月1日に延期され、認証ユーザは100回制限になりました(未認証ユーザは変わらず10回)。
そういう背景もあり他のコンテナレジストリへの移行を検討している人もいるかと思います。その候補としてGitHub Container registry (以下GHCR)も入ってくる可能性が高いのでこの記事を書いています。
要約
GHCRにはレート制限は基本的にない(2025/02/28現在)ので気にしなくてよいです。
終 制作・著作 ━━━━━ ⓃⒽⓀ
ただし、organization単位で集計して44,000 req/min を超えると制限がかるというAbuse rate limitがあるので、GHCRで多数のコンテナイメージやOCIアーティファクトを配布するときには少し気をつける必要があるかもしれません。 しかし後述しているようにHomebrewですらこの制限には達していないので基本は気にする必要はないです。
あくまで現時点での情報なので、実際にGHCRに移行する際には最新の情報を確認するようにしてください。
背景
昨年の9月頃、私が開発しているOSSである「Trivy」でのレート制限が多数報告されるようになりました。 最終的にコメントが100件以上、upvoteも200件を超えているので多くのユーザが影響を受けていたということが分かります。
GHCRにはレート制限はないという理解だったので改めて公式ドキュメントを確認しましたが、やはりレート制限の記述は見つかりませんでした。
なお、GitHubのREST APIのレート制限は以下に記述があります。
匿名ユーザだと60 req/hourで、認証をすると5000 req/hourまで緩和されます。しかしGHCRに関してはこの対象外のはずです。実際、イメージをpullしたあとにレート制限のステータスを確認してもAPI利用可能数が減りません。
それにも関わらず非常に多くのユーザから429 TOO MANY REQUESTSエラーが出ると報告があったので調査しました。
調査
エラーメッセージを見ると44000 req/minuteを超えており、脆弱性DBのダウンロードに失敗していると書いてありました。
TOOMANYREQUESTS: retry-after: 129.163µs, allowed: 44000/minute"
Trivyでは、脆弱性のスキャンに必要なデータベース(脆弱性DB)をOCIアーティファクトとしてGHCR (ghcr.io/aquasecurity/trivy-db) でホスティングしていました。このDBはキャッシュされるため一度ダウンロードされるとしばらくダウンロードされないのですが、CI/CDなどでキャッシュを使っていないとスキャンのたびにダウンロードされます。
ちなみに何でDBをGHCRにホストし始めたかというと、Homebrewがバイナリパッケージの配布にGHCRを使い始めたのを見たためです。
上の公式ブログにHomebrewがGHCRを使ってバイナリを配布していると堂々と書かれています。 あれほど有名なツールが使っているなら我々のような小さいツールが脆弱性DBの配布に使っても許されるだろうということで使い始めました。 ちなみにコンテナレジストリと言っているのでコンテナイメージしかpushできないと思う人もいるかも知れませんが、OCIレジストリは基本何でもpush可能で便利ストレージの側面があります。
確かにDBの配布を始めた当時はそこまでダウンロード数も多くなかったのですが、かなりの勢いでユーザ数が増えダウンロード数もどんどん増えていました。 2022年時点では1日あたり25万ダウンロードだったのですが、2024年1月の時点で300万ダウンロードされるようになっていました。2年弱で10倍以上に増えていました。

グラフを保存していなかったので問題の発生した2024年9月時点でどのぐらいか覚えていないですが、400万回ダウンロードぐらいだったかもしれません。
そこから逆算すると1分間あたり2,000~3,000ダウンロードになります。それでも44,000 req/minには到達しそうにないなと思ったのですが、GHCRがレート制限をどのようにリクエスト数を計算しているかは分かりませんでした。もしマニフェストファイルのpullやレイヤーのpullを別途加算しているとしたら上の数に2~3を掛ける必要があります。それでも多く見積もって6000~9000リクエストだし、やはり原因が分からなかったのでチケットを起票しました。
しかしGitHubから返信はなくユーザからの問い合わせは増える一方だったので、GitHubのサポートに問い合わせました。GHCRのレート制限はサポートの方々も知らない仕様だったせいか分かりませんが、あまり要領を得ないやり取りを何度か経たあと「aquasecurityというorganizationが44,000 req/minの制限に引っかかっている」という回答を得ました。
詳しく話を聞くと、悪用を防ぐためにorganization単位でレート制限を入れているとのことでした。Docker HubにもAbuse rate limitというのがあるので、似た制限だと思います。
Docker Hub has an abuse rate limit to protect the application and infrastructure. This limit applies to all requests to Hub properties including web pages, APIs, and image pulls. The limit is applied per IPv4 address or per IPv6 /64 subnet, and while the limit changes over time depending on load and other factors, it's in the order of thousands of requests per minute. The abuse limit applies to all users equally regardless of account level.
https://docs.docker.com/docker-hub/usage/#abuse-rate-limit
ただしDocker Hubと大きく異なるのはIPアドレス単位などではなくorganization単位で集計されるという点です。弊社はaquasecurity配下で複数のOCIアーティファクトを配布しています。
Packages · Aqua Security · GitHub
これには普通のコンテナイメージも含まれますし、その他のアーティファクトも含まれます。確かにこれら全てを集計すると10,000~20,000 req/minには到達しそうでした。それでも44,000 req/minは下回っていますが、24時間均等にリクエストがされるわけではないことを考慮するとアクセスの多い時間は44,000に到達する可能性があります。
その数日後、aquasecurity/ 配下の他のコンテナイメージもpullできない状況が発生するようになってしまいました。ユーザもまともに使えず、開発もこのために遅れるようになりいよいよ致命的な問題となりました。
回避策
GHCRでホストしている他のコンテナイメージやアーティファクトを巻き込んで制限されてしまうのは非常に問題だったので他の候補を色々模索しました。
我々の知る中ではAWS ECR Publicが一番良さそうでした。 未認証ユーザでも月に500GBまでpull可能ですし、認証すれば5TBまで無料でpullできます。有料なら5TB以上pullすることも可能です。
GHCRと違ってIPアドレスあるいはユーザ単位で、多く使いたい人はお金を払えばいいだけなので選択肢として魅力的でした。 ただ一つ問題なのは、我々のユーザの中にはAWSを使っていない人も多く、脆弱性DBのためにAWSアカウントを作れというのはOSSとして少し厳しそうでした。 もちろん500GBまでなら未認証でも使えはしますが、ヘビーユーザは足りません。
しかし他に候補もなかったので仕方ないかーなどと言ってKubeCon North America 2024に発表に行ったわけなのですが、そこで多くの人から「Trivyを使っている。本当にありがとう。」と言っていただくのと同時に「GHCRのレート制限で困っているので何とかならないか?」と聞かれました。
「何とかなりません」と答えていたのですが、元GoogleでContainer Registry(現Artifact Registry)の開発を担当していた人がやってきて 「mirror.gcr.io は制限ないから使えばいいよ」と教えてくれました。「何だそれは聞いたことないぞ」と調べたら確かに存在しました。
しかし詳細はあまり書いてありませんし、使っているという話もあまり聞いたことがありません。 検索してもほぼ情報は出てきませんでした。 自分が知らないだけなのかもしれませんが、少なくともKubeConで出会った元Googleの人(つまり内部の人)以外は誰も知らなかったので、知名度は高くないと思われます。
mirror.gcr.io は恐ろしいことにレート制限がありません。動作としてはキャッシュされていればそのまま返し、キャッシュされていなければDocker Hubからイメージを持ってきてキャッシュしてくれます。つまりレジストリ名だけ変えればDocker Hubにアクセスするのと同じように使えます。docker.io/aquasec/trivy-db にホストしているイメージは mirror.gcr.io/aquasec/trivy-db でpull可能です。
注意点としてはあくまで現時点での話です。 Googleフォトもかつては容量無制限だったことを考えると...
飛行機に長時間乗るのが嫌いなのでカンファレンスは基本行かないのですが、やはりこういう廊下でしか得られない情報があるので、もっと積極的に行ったほうが良いなと思いました(などと言いつつKubeCon EU 25は行かないことにしました)。20時間以上飛行機に乗って辛かったのですが、 mirror.gcr.io を教えてもらっただけで行った甲斐がありました。
GITHUB_TOKENについて
通常のAPIレートリミットとは異なり、個々のユーザがPATを使って認証したり、GitHub Actionsで${{ secrets.GITHUB_TOKEN }}を設定しても、このorganization全体に適用されるAbuse rate limitには影響しません。
他のコンテナレジストリなどでよくある「匿名なら200プル/6時間だけど、認証すれば上限が上がる」という形ではありません。
備考
我々でアウトならHomebrewはもっと頻繁にレート制限にかかっていそうだなと思って調べたら一番ダウンロードされているsqliteで1億ダウンロードでした。
我々の脆弱性DBはトータルで20億ダウンロードなので完全に使い方が悪いです。GHCRは全く悪くありません。普通に考えて44,000 req/minにはまず到達しません。正直思っていた以上の速度でユーザ数が増えました。
ただorganization単位で集計されるため、悪意あるユーザ(あるいは悪意がなくても設定をミスしたユーザが)がいると簡単に特定のorgを利用不能に出来る点は気になります。例えばKubernetes SIGsの適当なイメージをpullしまくるとkubernetes-sigsの配下の全てのイメージがアクセス不能になります。
Packages · Kubernetes SIGs · GitHub
そういう点を考慮すると、GHCRもREST APIやDocker Hubと同様IPアドレスあるいはユーザ単位のレート制限の方が良いのではないかと思ったので一応上の懸念について伝えたのですが、現状このレート制限に引っかかったことがあるのは恐らく我々だけなので、我々の使い方が悪いという結論で終わりそうではあります。正直申し訳ないという気持ちです。
余談
前述したように脆弱性DBはキャッシュされるので、ダウンロード数とスキャン数には大きな乖離があります。 実際にGitLabなど顧客にTrivyを使ったサービスを提供している組織では、脆弱性DBを自分たちのサーバでキャッシュしてユーザに配布しています。 この場合は我々から見えるダウンロード数は1回ですがスキャン回数は数百万回ということがありえます。
さらに最近はIaCスキャン機能の認知度が上がってきて、そちらも多く使われています。IaCスキャンの場合は脆弱性DBのダウンロードは行われないのでダウンロード数には計上されません。
これらを考慮すると毎日数千万回とか実行されていそうなので、丁寧な開発を行わなければと身の引き締まる思いがしました。なお、その直後のリリースでカジュアルに致命的なバグを埋め込みました。
まとめ
GHCRは普通に使う分にはレート制限を気にする必要はないです。 我々以外に困る人はいないだろうと思って特に書いていませんでしたが、 @__syumai さんが言及してくださっていたので一応書いておきました。