CI における Docker Hub Pull Rate Limit を Organization Access Tokens で回避しよう
Docker Hub Pull Rate Limit の CI への影響
2025年4月1日から未認証の Docker ユーザーは、Docker Hub からの Pull が1時間あたり10回に制限されます(Pull Rate Limit)。
Pull Rate Limit を超えた場合には以下のようなメッセージが表示されます。
You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
Docker(Hub)にログインすることでこの問題を解決することができ、Personal プランをご利用の方は 1時間あたり100回、それ以上のプラン(Pro、Team、Business)をご利用の方は制限なくご利用いただくことができます。
ローカル開発環境で既に Docker Desktop をお使いの方は、Docker Desktop にサインインするのみでこの問題は解決することができます。
しかし、CI パイプライン で Docker Hub からの Pull を利用している場合、Pull Rate Limit の影響を受けやすいので注意が必要です。
理由としては、以下が挙げられます。
- CI パイプラインのあらゆるところで Docker Hub からの Pull が必要な箇所がある
- Docker ビルド → ベースイメージを Docker Hub から Pull する必要がある
- CI の実行環境として Docker コンテナ を利用している(CircleCI の Docker Executor など)
- Testcontainers など、Docker コンテナを使ったテストの実行
- あらゆる開発者が CI パイプラインを実行させるため、ローカル開発環境よりも Docker Hub からの Pull が必要な回数が多くなりがち
- 特にマネージド型のCIサービスでは、パイプライン実行毎にクリーンな環境が提供されるため、ローカルイメージが残っておらず Docker Hub からの Pull が必要な場合が多い
※ いくつかのCIサービス(CircleCIなど)では現段階で Pull Rate Limit の対象外になっている場合がありますが、セルフホストランナーを利用している場合には Pull Rate Limit の対象になる可能性があります。
これまでの対策としては、Docker のパーソナルアクセストークンを発行し、CIパイプラインでDocker(Hub)にログインする必要がありました。
しかし、パーソナルアクセストークンは個人ユーザーに紐づいて管理されてしまうので、CI パイプラインで利用するのはなるべく避けたいです。
そこで、今回はパーソナルアクセストークンに代替する Organization Access Token を利用する方法について紹介します。
Organization Access Token とは?
Organization Access Token は Docker Team および Business サブスクリプションをご利用の方が利用できる機能です。
※ 2025年3月現在 Beta 版として提供しています
Organization Access Token はユーザー個人ではなく、サブスクリプションに所属する Organization としてアクセストークンを発行・管理することができます。
そのため、パーソナルアクセストークンのように個人ユーザーに紐づいて管理されてしまう心配をする必要がなく、より安全に CI パイプラインに利用するアクセストークンを管理することができます。
Organization Access Token を発行する
Organization Access Token を作成する手順は以下です。
※ Organization あるいは Company の Owner 権限を持つ方のみ操作できます
-
Docker Admin Console にアクセスします
-
Organization Access Token を作成する Organization を選択します
-
Security and access の Access tokens を開きます
-
Generate access token を選択します
-
Label(ラベル)、Access Token Description(説明)、Expiration Date(期限)を記入します。
-
トークンの リポジトリアクセス権限 を設定します
- Public repositories (読み取り専用)
- All repositories: 読み取り専用 or 読み書き可能
- Select repositories: 最大 50 個のリポジトリを選択し、それぞれ読み取り専用 or 読み書き可能を設定
-
Generate token を選択し、表示されたトークンをコピーして保存します
Organization Access Token を CI で利用する
Organization Access Token が発行できたら、それらを各 CI プラットフォームのシークレットに保存し、実際に Docker Hub から Image を Pull するステップの前に docker login
を実行させるようにします。
Docker CLI を使った例(AWS CodeBuild, Jenkins, GitLab)
Docker CLI の docker login
コマンドによってログインすることができます、--username
を対象の Organizaion 名に、--password
を Organization Access Token に指定します。
以下は AWS CodeBuild のパイプライン例です
version: 0.2
env:
secrets-manager:
DOCKER_ORG: ${SECRETS_NAME}:DOCKER_ORG
DOCKER_ORG_TOKEN: ${SECRETS_NAME}:DOCKER_ORG_TOKEN
phases:
pre_build:
commands:
- echo "$DOCKER_ORG_TOKEN" | docker login --username $DOCKER_ORG --password-stdin
build:
commands:
- docker build --push --tag user/app:latest .
以下は Jenkins のパイプライン例です
pipeline {
agent any
environment {
DOCKER_ORG: credentials('docker-org')
DOCKER_ORG_TOKEN: credentials('docker-org-token')
}
stages {
stage('Build') {
steps {
sh 'echo "$DOCKER_ORG_TOKEN" | docker login --username $DOCKER_ORG --password-stdin'
sh 'docker build --push --tag user/app:latest .'
}
}
}
}
以下は GitLab のパイプライン例(dindを使ったイメージビルド)です
docker-build:
image: docker:cli
stage: build
services:
- docker:dind
before_script:
- echo "$DOCKER_ORG_TOKEN" | docker login --username $DOCKER_ORG --password-stdin
script:
- docker build --push --tag user/app:latest .
GitHub Actions(docker/login-action)
docker/login-action の username
を対象の Organizaion 名に、password
を Organization Access Token に指定します。
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKER_ORG }}
password: ${{ secrets.DOCKER_ORG_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: user/app:latest
CI の実行環境として Docker コンテナ を利用している(CircleCI Docker Executor)
CircleCI の Docker Executor など、CI の実行環境として Docker コンテナ を利用している場合には、Docker Hub に認証した上で Pull するように設定します。
auth.username
を対象の Organizaion 名に、auth.password
を Organization Access Token に指定します。
jobs:
build:
docker:
- image: myorg/myrepo
auth:
username: $DOCKER_ORG
password: $DOCKER_ORG_TOKEN
steps:
- run: echo "hello"
Discussion