🐙

DockerコンテナをAWS CodeBuildでビルドする際のToo Many Requestsエラーへの対応

2022/03/09に公開約4,200字

概要

Docker コンテナを AWS CodeBuild でビルドする際に、ビルドプロセスが失敗する場合があります。
調べてみたところ、DockerHub からコンテナイメージを Pull する際に、次のようなエラーが発生する場合があることがわかりました。

toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit

[Container] 2022/03/09 03:53:34 Command did not exit successfully docker build -t $REPOSITORY_URI:latest . exit status 1
[Container] 2022/03/09 03:53:34 Phase complete: BUILD State: FAILED
[Container] 2022/03/09 03:53:34 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: docker build -t $REPOSITORY_URI:latest .. Reason: exit status 1

2020 年 8 月に Docker Hub でコンテナイメージの Pull 回数にレート制限をもうけるということが発表されており、以下のようなレート制限になっています。

プラン レート制限
無料プラン(匿名ユーザー) 100 pull/6 時間あたり
無料プラン(認証ユーザー) 200 pull/6 時間あたり
Pro 無制限
Team 無制限

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

回数としては通常利用する上では十分なようにも思えますが、匿名ユーザの場合、プル率の制限は個々の IP アドレスに基づきますという記載があり、AWS の CodeBuild が IP アドレスを共有している関係で、利用状況によって成功したり失敗したりするという状態になります。

これを回避するためには、CodeBuild のプロセスの中で、DockerHub のユーザ認証(個別に作成した DockerHub ユーザでの認証)を行う必要があります。

その場合、DockerHub のユーザ情報を AWS 上で管理して、CodeBuild 側に安全に引き渡して使用する必要があります。
管理のためには、AWS のパラメータストアSecrets Managerを用います。

以下にパラメータストアを用いた場合の手順を記載します

手順

パラメータストアへの Username、Password の登録

まず、パラメータストアに DockerHub の Username、Password を登録します。

設定手順

  1. AWS コンソールより、AWS Systems Manager-パラメータストアを開きます。
  2. パラメータの作成を押下します。
  3. 以下のような内容で、登録を行います。
名前 タイプ KMS キーソース
/dockerhub/user 安全な文字列 任意のキーを選択 DockerHub にログインするユーザ名
/dockerhub/pass 安全な文字列 任意のキーを選択 DockerHub にログインするパスワード

CodeBuild プロジェクトへのパラメータ参照の設定

CodeBuild プロジェクトに対して、パラメータストアを参照して、環境変数に引き渡す設定を行います。

設定手順

  1. AWS コンソールより、CodeBuild-ビルドプロジェクトを開きます。
  2. 対象のプロジェクトを選択し環境を選択します。
  3. 追加設定-環境変数に以下の内容で設定します。
名前 タイプ
DOCKERHUB_USER /dockerhub/user パラメータ
DOCKERHUB_PASS /dockerhub/pass パラメータ

CodeBuild のサービスロールに対して、権限を付与する

CodeBuild のサービスロールに対して、パラメータストアにアクセスするための権限(ssm:GetParameters)を付与する必要があります。

権限がない場合以下のようなエラーになります。

[Container] 2022/03/09 05:35:44 Phase context status code: Decrypted Variables Error Message: AccessDeniedException: User: arn:aws:sts::<ACCOUNT ID>:assumed-role/codebuild-XXXXXX-service-role/AWSCodeBuild-XXXXXXXXXXXXXXXXXXX is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-northeast-1:<ACCOUNT ID>:parameter/dockerhub/pass because no identity-based policy allows the ssm:GetParameters action

設定対象のサービスロールは CodeBuild プロジェクトを作成した際に作成した、以下のようなロールになります。

arn:aws:iam::<ACCOUNT ID>:role/service-role/codebuild-XXXXXX-service-role

設定手順

  1. AWS コンソールより、IAM-ロールを選択します。
  2. 対象のロールを検索します。(codebuild-などで絞り込みます)
  3. 対象ロールを選択し、アクセス許可を追加-ポリシーをアタッチを選択します。
  4. AmazonSSMReadOnlyAccessを選択して追加します。より細かくアクセス制御する場合は、ポリシーを追加して細かく条件設定します。ssm:GetParameters で対象のパラメータを取得できるようにします。
  5. ポリシーをアタッチを押下します。

buildspec.yml に DockerHub への個別ユーザでのログイン処理追加

buildspec.ymlに以下のような処理を追加します。

DockerHub ログイン

- echo Logging in to Docker Hub...
- echo ${DOCKERHUB_PASS} | docker login -u ${DOCKERHUB_USER} --password-stdin

以下のような記載になります。

buildspec.yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR... test2
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin <ACCOUNT ID>.dkr.ecr.ap-northeast-1.amazonaws.com
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
      - echo Logging in to Docker Hub...
      - echo ${DOCKERHUB_PASS} | docker login -u ${DOCKERHUB_USER} --password-stdin

上記の状態で、ビルドを実行すると、コンテナイメージの PULL が問題なく行えるようになります。

Discussion

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