生産性向上ブログ

継続的な生産性向上を目指すエンジニアのためのブログ

Docker Hub の pull rate limit について現状まとめ

Docker Hub の pull rate limit が 8 月に発表され、この記事執筆時点(11/15)で適用されつつあります。この pull rate limit の情報がいろいろなところに散らばっていてわかりづらくなってきたので、自分自身の情報整理のためにこの記事に現状をまとめてみました。

TL;DR

  • Docker Hub から pull するときは認証しておくのが無難です

背景

www.docker.com

↑の記事によると、Docker Hub の 30% のダウンロードは 1% の匿名ユーザー(認証なしで利用するユーザー)によるもの、という分析を元に今回の pull rate limit を設定したと書かれています。

ちなみに、使われてない Docker イメージを自動で削除するという話もあったのですが、2021 年以降に延期になりましたので、今回の記事では特に触れません。

Docker Hub の pull rate limit

www.docker.com

プランによる制限内容の違いは↑の料金ページにまとまっています。pull rate limit についての情報だけをまとめると、以下のようになります。

ユーザーの種類 pull rate limit
匿名ユーザー 100 pull / 6 時間
Free プラン 200 pull / 6 時間
Pro プラン 無制限
Team プラン 無制限

docs.docker.com

↑の記事のよると、

Unauthenticated (anonymous) users will have the limits enforced via IP.

と書かれているので、匿名ユーザーは IP アドレスで同じユーザーと判定されます。会社のネットワークのように、社外のインターネットにアクセスするときに NAT 経由で同じ IP アドレスになるケースでは、自分がほとんど使っていなくても制限にかかる可能性があります。

pull rate limit で見ると匿名ユーザーと Free プランは大きく変わらないように見えますが、認証していれば Free プランでも Docker ID で判別されるため、上記のような問題が発生しなくなる点が大きいです。このため、Free プランでも pull するときは認証しておくことが余計なトラブルを避けるために重要になります

pull rate limit の回数カウントの定義

www.docker.com

↑の記事の "Helping developers understand pull rate limits" に、pull rate limit がどのように回数をカウントしているのか仕組みが書かれています。

まず、Docker の pull は、1 つの API の実行ではなく、manifest のダウンロード API と Docker イメージのレイヤー(blob) のダウンロード API の実行の組み合わせで実現されています。このため、Docker Hub 側としては純粋な pull の回数はカウントできず、manifest のダウンロードか Docker イメージのレイヤーのダウンロード回数しかカウントできません。そして、pull rate limit の回数は、Docker イメージのレイヤーのダウンロード回数ではなく、manifest のダウンロード回数で決まります

pull を実行すると、まず manifest をダウンロードし、manifest で定義されている情報を元にまだ手元に存在しない Docker イメージのレイヤーをダウンロードします。複数の CPU アーキテクチャをサポートしている Docker イメージを pull する場合、まずサポートしているアーキテクチャのリストの manifest をダウンロードし、その情報を元に Docker を動かしてる環境の CPU アーキテクチャの manifest をダウンロードします。つまり、1 回の pull に対して、1 回か 2 回の manifest のダウンロードと、0 回から複数回の Docker イメージのレイヤーのダウンロードが発生します。

このため、Docker イメージのレイヤーのダウンロード回数を pull rate limit の回数としてカウントしてしまうと、Docker イメージ側でレイヤー数を減らすようなよくない方向に進んでしまう危険性があるため、manifest のダウンロード回数を pull rate limit の回数としてカウントするようになったようです。

ただし、すでに手元にある Docker イメージを pull するときでも manifest のダウンロードは発生するため、pull rate limit の回数としてカウントされてしまうというトレードオフも発生しています。

pull rate limit の適用スケジュール

www.docker.com

↑に pull rate limit の適用状況の詳細が書かれています。今後も最新の情報に更新されていくと思われます。

いきなり最終的な pull rate limit(匿名ユーザー 100 回、Free プラン 200 回)が適用されるわけではなく、11/2 から徐々に回数を下げる形で制限を厳しくしていっているようです。ただし、一時的に最終的な pull rate limit を適用している時間帯もあるようなので、利用者側としてはもう最終的な pull rate limit を前提にして Docker Hub の利用方法を見直すのがいいでしょう。

現在の pull rate limit の確認方法

www.docker.com

↑の記事で、手元の環境で現在の pull rate limit の状態を確認する方法が紹介されています。

manifest ファイルのダウンロード API のレスポンスヘッダーに、以下のヘッダーが含まれるようになっています。

  • RateLimit-Limit: 6 時間の pull rate limit 上限
  • RateLimit-Remaining: 6 時間の pull rate limit 残り回数

手元で試すには、まずトークンを取得します。

匿名ユーザーの場合、以下を実行します。

$ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)

認証する場合、以下を実行します。(username:password を自身の Docker ID とパスワードに置き換えてください)

$ TOKEN=$(curl --user 'username:password' "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)

トークンを取得したら、manifest ダウンロード API を実行してレスポンスヘッダーを取得します。

$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep RateLimit
RateLimit-Limit: 500;w=21600
RateLimit-Remaining: 500;w=21600

この記事執筆時点(11/15)では、pull rate limit の上限は 500 回になっています。11 月頭に確認したときは 5,000 回だったのですが、徐々に下がってきています。これが最終的には匿名ユーザー 100 回、Free プラン 200 回となるはずです。

本来は manifest のダウンロードのたびに RateLimit-Remaining が減るはずなのですが、どうも今回ダウンロードしている ratelimitpreview/test の manifest は例外なのか、RateLimit-Remaining が減りませんでした。

pull rate limit の例外

いくつか pull rate limit の例外となるケースがあります。

OSS

www.docker.com

↑の記事に書かれている通り、条件にマッチする OSS の Docker イメージは、申請してレビューで承認されれば、その namespace 以下のイメージに対しては誰が利用しても pull rate limit のカウント対象とはならないようです。

例外となっている namespace 一覧のようなものは今のところ見当たらないので、利用中の OSS が例外となっているかは個別に確認するしかないですかね。どこかにまとまっていたら教えてほしいです。

サービス

ユーザー数の多い CI/CD など、Docker 社とパートナーになった一部サービスの利用ユーザーは pull rate limit の例外とする動きがあります。

support.circleci.com

例えば、クラウド版 CircleCI は↑の記事で Docker executor を使った場合は pull rate limit の対象とならないと告知しています。(ちなみに、クラウド版 CircleCI の外からのアクセスでも circlecicimg の namespace は pull rate limit の例外となります)

github.com

公式発表ではありませんが、GitHub Actions も GitHub の中の人が pull rate limit の対象外になると書いています。この記事執筆時点(11/15)で GitHub Actions を試したところ、manifest のダウンロード API が RateLimit-* ヘッダーを返さないため、すでに例外として扱われているものと思われます。(セルフホストランナーは除きます)

こちらも例外となっているサービス一覧のようなものが見当たらないので、利用ユーザーは Docker Hub を利用しているサービスが例外になっているか個別に確認するしかないですね。どこかにまとまっていたら教えて(ry。

また、例外扱いが将来的にもずっと続くのかはわからないので、認証しておくほうが無難だとは思います。

ミラー

会社のように、環境内に Docker を実行するマシンがたくさんある場合は、Docker Hub へのミラーを構築して、各マシンで動く Docker はそのミラーを経由するように設定する方法が考えられます。その場合、ミラーに Team プランのアカウントを設定しておくだけになるので、認証が楽になると考えられます。

docs.docker.com

↑で公式のミラー構築方法と Docker daemon 側の設定方法が書かれています。ミラーは複数設定できるので、冗長性を持たせて運用することが可能です。

AWS ユーザー向け Docker Hub の public イメージの利用チェックツール

github.com

AWS は Docker Hub の public イメージの利用をチェックするためのシェルスクリプトのツール群を公開しています。AWS を使ってないユーザーでも、どうやって Docker Hub への依存を洗い出すかの参考になるかと思います。

Docker Hub の代替サービス

最後に、自分が知っている範囲で Docker Hub 以外の Docker レジストリサービスの選択肢を書いておきます。

www.kaizenprogrammer.com

まず、↑で以前に紹介した GitHub Container Registry です。GitHub Container Registry は、public イメージなら完全無料です。ただし、まだベータなので、なにかしら問題が発生する可能性はあります。

また、筆者は利用したことがないですが、GCP の Container Registry も選択肢になりそうです。ただ、public なイメージでも下りのネットワーク料金がかかるようです。

AWS の ECR は、現時点ではイメージを public に公開する機能がないですが、将来的に public なレジストリを提供するというアナウンスがあります。こちらも一定の帯域以上のネットワーク転送は有料となりそうです。

他には、Red Hat が提供する Quay.io が、public なイメージも公開可能です。こちらは料金体系が独特で、private リポジトリ数でプランが変わり、public リポジトリ数やユーザー数、ネットワーク転送量では料金が変わらないというモデルになっています。正直どこで儲けるのか謎です。

いくつか紹介しましたが、自身の管理しているイメージは他のレジストリに楽に移行できますが、外部で管理されている Docker Hub のイメージに依存している場合は、自前で Docker Hub 上のイメージを自分たちが利用するレジストリに push する必要があるので、なかなか大変にはなりそうです。

まとめ

長々と書きましたが、TL;DR に書いたとおり、Docker Hub を利用するときは認証しておくのが無難です。ただ、個人に紐付かない bot 的なマシンアカウント(サービスアカウント)の管理が面倒にはなりそうです。

pull rate limit の目的が背景に書いたとおり一部の過剰アクセスな匿名ユーザーを制限することが目的であれば、サービスの例外扱いがもっと増えて、一般的なユーザーは認証しなくてもあまり影響のない状況に落ち着く可能性もありそうに思います。しかし、認証しないと予想外のタイミングで pull rate limit にハマるリスクが残ります。特に、プロダクション環境が Docker Hub に依存していないかはよく調べておく必要があります。

まだ変更の過渡期なので正直判断が難しい部分がありますが、すでに pull rate limit は適用されつつあるので、早めに Docker Hub への依存を洗い出して今後の方針を検討しておくことをおすすめします。