Zenn
🔐

CI における Docker Hub Pull Rate Limit を Organization Access Tokens で回避しよう

2025/03/06に公開

Docker Hub Pull Rate Limit の CI への影響

2025年4月1日から未認証の Docker ユーザーは、Docker Hub からの Pull が1時間あたり10回に制限されます(Pull Rate Limit)。

https://docs.docker.com/docker-hub/usage/

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)にログインする必要がありました。

https://docs.tadashi0713.dev/docker-security-ja/for-developers/access-tokens

しかし、パーソナルアクセストークンは個人ユーザーに紐づいて管理されてしまうので、CI パイプラインで利用するのはなるべく避けたいです。

そこで、今回はパーソナルアクセストークンに代替する Organization Access Token を利用する方法について紹介します。

Organization Access Token とは?

Organization Access Token は Docker Team および Business サブスクリプションをご利用の方が利用できる機能です。

※ 2025年3月現在 Beta 版として提供しています

https://docs.tadashi0713.dev/docker-security-ja/for-admins/access-tokens

Organization Access Token はユーザー個人ではなく、サブスクリプションに所属する Organization としてアクセストークンを発行・管理することができます。

そのため、パーソナルアクセストークンのように個人ユーザーに紐づいて管理されてしまう心配をする必要がなく、より安全に CI パイプラインに利用するアクセストークンを管理することができます。

Organization Access Token を発行する

Organization Access Token を作成する手順は以下です。

※ Organization あるいは Company の Owner 権限を持つ方のみ操作できます

  1. Docker Admin Console にアクセスします

  2. Organization Access Token を作成する Organization を選択します

  3. Security and accessAccess tokens を開きます

  4. Generate access token を選択します

  5. Label(ラベル)、Access Token Description(説明)、Expiration Date(期限)を記入します。

  6. トークンの リポジトリアクセス権限 を設定します

    • Public repositories (読み取り専用)
    • All repositories: 読み取り専用 or 読み書き可能
    • Select repositories: 最大 50 個のリポジトリを選択し、それぞれ読み取り専用 or 読み書き可能を設定
  7. 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-actionusername を対象の 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"

https://circleci.com/docs/ja/private-images/

https://support.circleci.com/hc/en-us/articles/360049758552-My-build-fails-to-pull-Docker-image-with-Too-Many-Requests-Rate-Limiting-by-Docker-Hub

Discussion

ログインするとコメントできます