DockerコンテナをAWS CodeBuildでビルドする際のToo Many Requestsエラーへの対応
概要
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 | 無制限 |
回数としては通常利用する上では十分なようにも思えますが、匿名ユーザの場合、プル率の制限は個々の IP アドレスに基づきます
という記載があり、AWS の CodeBuild が IP アドレスを共有している関係で、利用状況によって成功したり失敗したりするという状態になります。
これを回避するためには、CodeBuild のプロセスの中で、DockerHub のユーザ認証(個別に作成した DockerHub ユーザでの認証)を行う必要があります。
その場合、DockerHub のユーザ情報を AWS 上で管理して、CodeBuild 側に安全に引き渡して使用する必要があります。
管理のためには、AWS のパラメータストア
かSecrets Manager
を用います。
以下にパラメータストア
を用いた場合の手順を記載します
手順
パラメータストアへの Username、Password の登録
まず、パラメータストアに DockerHub の Username、Password を登録します。
設定手順
- AWS コンソールより、
AWS Systems Manager
-パラメータストア
を開きます。 -
パラメータの作成
を押下します。 - 以下のような内容で、登録を行います。
名前 | タイプ | KMS キーソース | 値 |
---|---|---|---|
/dockerhub/user | 安全な文字列 | 任意のキーを選択 | DockerHub にログインするユーザ名 |
/dockerhub/pass | 安全な文字列 | 任意のキーを選択 | DockerHub にログインするパスワード |
CodeBuild プロジェクトへのパラメータ参照の設定
CodeBuild プロジェクトに対して、パラメータストアを参照して、環境変数に引き渡す設定を行います。
設定手順
- AWS コンソールより、
CodeBuild
-ビルドプロジェクト
を開きます。 - 対象のプロジェクトを選択し
環境
を選択します。 -
追加設定
-環境変数
に以下の内容で設定します。
名前 | 値 | タイプ |
---|---|---|
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
設定手順
- AWS コンソールより、
IAM
-ロール
を選択します。 - 対象のロールを検索します。(
codebuild-
などで絞り込みます) - 対象ロールを選択し、
アクセス許可を追加
-ポリシーをアタッチ
を選択します。 -
AmazonSSMReadOnlyAccess
を選択して追加します。より細かくアクセス制御する場合は、ポリシーを追加して細かく条件設定します。ssm:GetParameters
で対象のパラメータを取得できるようにします。 -
ポリシーをアタッチ
を押下します。
buildspec.yml に DockerHub への個別ユーザでのログイン処理追加
buildspec.yml
に以下のような処理を追加します。
DockerHub ログイン
- echo Logging in to Docker Hub...
- echo ${DOCKERHUB_PASS} | docker login -u ${DOCKERHUB_USER} --password-stdin
以下のような記載になります。
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