CodeBuildでECRビルドエラーから得た4つの知見

![Screenshot from 2019-09-09 02-22-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/fc2b853c-d2b3-0c59-b4c8-c27edc65b49e.png)

# はじめに
ECRをただビルドしたかった...はじめて使うといろいろハマりポイントが多くてたくさん調べる羽目に
自分自身が次ハマらないようにまとめておく。

# TL;DR
- 1.`aws/codebuild/standard:2.0` を使用するときは `runtime-versions` を指定する必要がある
- 2.ビルドを実行するロールにECRを操作するポリシーを追加する必要がある
- 3.Dockerの特権付与チェックを入れる必要がある
- 4.ECRの「プッシュコマンドの表示」をよく見て環境変数を設定する


# 4つのエラー詳細と対応方法

## 1.`aws/codebuild/standard:2.0` を使用するときは `runtime-versions` を指定する必要がある

~~~
YAML_FILE_ERROR: This build image requires selecting at least one runtime version.
~~~

- 今回はDockerを利用していたため以下の設定を`buildspec.yml`に追記する必要があった。

~~~ yaml:buildspec.yml
phases:
  install:
    runtime-versions:
      docker: 18
~~~

## 2.ビルドを実行するロールにECRを操作するポリシーを追加する必要がある

~~~
COMMAND_EXECUTION_ERROR: Error while executing command: $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION). Reason: exit status 255
~~~

- デフォルトではECRのポリシーは設定されていない。
- 自分で設定を追加する必要がある
- IAMでロールに**AmazonEC2ContainerRegistryPowerUser**(ECRの操作を許可する)ポリシーをアタッチ

## 3.Dockerの特権付与チェックを入れる必要がある

~~~
[Container] 2019/09/07 17:00:26 Running command docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG . 
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 
~~~
- Dockerデーモンが起動していないようなエラーが発生
- CodeBuildは実行自体がDocker(Ubuntuなど選択)だが、その中でDockerを使うため、チェックが必要になる

![Screenshot from 2019-09-09 02-49-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/28c40647-fe76-cea3-07e9-cbe9efc55523.png)

- Docker in Dockerのような実行Docker(Ubuntu)の上でECRをBuildするためのDockerが動作しているイメージ

![Screenshot from 2019-09-09 03-03-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/5cde052f-2fa5-c277-5dd0-1a06dca6f671.png)

## 4.ECRの「プッシュコマンドの表示」をよく見て環境変数を設定する

~~~
[Container] 2019/09/07 17:32:13 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: docker push
$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG. Reason: exit status 1 
~~~

- アカウントIDの環境変数にずっとIAMユーザー名を入れるミスをしていた。
- ECRの「プッシュコマンドの表示」にプッシュに必要な環境変数の設定サンプルがあるので確認する
- 隠した部分をよく見れば、アカウントIDだと気がつくことができた

![Screenshot from 2019-09-09 03-16-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/84d09170-282d-4a3b-fd8d-630ac60cb417.png)

- ちなみにbuildにつかった`buildspec.yml`はこちら。
- 原始的だが、`echo`でログを出していく事もミス発見に繋がった。

~~~ yaml:buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - echo $IMAGE_REPO_NAME
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - echo docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - printf '[{"name":"<container-definition>","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > artifacts.json

artifacts:
  files: artifacts.json
~~~

# さいごに
- ECRのbuild&pushを行うときのハマりポイントは理解さえすれば二度とハマらない内容でした。
- 手動より楽なことを実感できたのでパイプライン等と組み合わせてどんどん最適化していきたいです。
- [こちらのブログ](https://icck.github.io/posts/)にもAWS関連いくつか記事を書き始めました。