AWS CodeBuildでDockerイメージをビルドする際にビルドフェーズを意識してbuidspecを書く

システム開発部Misocaチームエンジニアの id:mizukmb です。

Misocaチームでは、DockerイメージのビルドをAWS CodeBuildを利用して日々ビルドをしています。

CodeBuildではbuildspecと呼ばれるファイルに docker builddocker push といったコマンドを記述することで、CodeBuildを起動した際にこれらのコマンドを自動で実行することができます。

このbuildspecにはビルドフェーズがあり、それぞれのフェーズに適した処理を記述する事が推奨されています。この辺りを意識してDockerイメージのビルドからECRのプッシュまでをbuildspecに記述したいと思います。

ビルドフェーズとは

CodeBuildには phases/installphases/build といった決められたビルドフェーズがいくつかあり、各フェーズに適したコマンドを配置する事がAWSのドキュメントにより推奨されています。

docs.aws.amazon.com

例えば phases/install はAWSのドキュメントでは以下のように書かれています。

install フェーズは、ビルド環境でのパッケージのインストールにのみ使用することをお勧めします。たとえば、このフェーズを使用して、Mocha や RSpec などのコードテストフレームワークをインストールすることができます。

( https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html より引用 )

また、ビルドフェーズは各フェーズで成功/失敗した場合にどのフェーズに遷移するかが決められています。このフローチャートは以下のドキュメントの ビルドフェーズの移行 から確認できます。

docs.aws.amazon.com

これらを意識して書かれたbuildspecについて次の章にて解説します。

buildspec

app:latest というタグ名のDockerイメージをビルドし、ECRにプッシュする。プッシュの前にDockerイメージの内容が期待通りであるか Gossを使ってサーバーテストを実行し、失敗したらプッシュを行わずにCodeBuildの実行を終了する。

というような処理を先ほど説明したビルドフェーズを意識して書いてみると以下のような内容になります。

version: 0.2
phases:
  install:
    commands:
      - curl -L https://raw.githubusercontent.com/aelsabbahy/goss/master/extras/dgoss/dgoss -o /usr/local/bin/dgoss
      - chmod +rx /usr/local/bin/dgoss
      - curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.16/goss-linux-amd64 -o /usr/local/bin/goss
      - export GOSS_PATH=/usr/local/bin/goss
      - export GOSS_FILES_PATH=config/docker/spec
  pre_build:
    commands:
      - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com
  build:
    on-failure: ABORT
    commands:
      - docker build -t app:latest .
  post_build:
    commands:
      - dgoss run app:latest
      - docker tag app:latest  XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest
      - docker push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest

それぞれのフェーズについて先ほど紹介したAWSのドキュメント CodeBuild のビルド仕様に関するリファレンス - AWS CodeBuild の内容をベースに解説します。

phases/install

install フェーズではビルド等に必要なパッケージのインストールが推奨されています。 aws , docker コマンドはCodeBuild実行環境にはプリインストールされているので、このフェーズでは goss とDockerイメージをテストするためのラッパースクリプト dgoss をインストールします。環境変数 GOSS_PATHGOSS_FILES_PATHdgoss の実行に必要なので一緒に設定します。

gossdgoss のインストールについてはこちらのREADMEを参考にしています

  install:
    commands:
      - curl -L https://raw.githubusercontent.com/aelsabbahy/goss/master/extras/dgoss/dgoss -o /usr/local/bin/dgoss
      - chmod +rx /usr/local/bin/dgoss
      - curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.16/goss-linux-amd64 -o /usr/local/bin/goss
      - export GOSS_PATH=/usr/local/bin/goss
      - export GOSS_FILES_PATH=config/docker/spec

phases/pre_build

pre_build フェーズではビルド前に必要なコマンドを実行する事が推奨されています。ECRにサインインしておきます。

  pre_build:
    commands:
      - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com

phases/build

build フェーズではビルドを実行するコマンドを記述する事が推奨されています。今回のメインである docker build を記述します。

docker build が失敗してDockerイメージが作成できなかった場合、 post_build フェーズに移行してもサーバーテストの実行やECRへのプッシュを行えないので on-failure: ABORT を設定してビルドを中止します。

  build:
    on-failure: ABORT
    commands:
      - docker build -t app:latest .

phases/post_build

post_build フェーズはビルド後に行うコマンドを記述する事が推奨されています。ここではGossの実行やECRへのDockerイメージプッシュを行います。

  post_build:
    commands:
      - dgoss run app:latest
      - docker tag app:latest  XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest
      - docker push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest

おわりに

ビルドフェーズを意識したDockerイメージのビルドとプッシュを行うbuildspecの書き方について書きました。CodeBuildはビルドフェーズを意識せずに例えば全てのコマンドを install フェーズに書いても期待通りに動作します (今回でいえばECRのプッシュまで出来てしまう)。ですが、ビルドフェーズを意識することでより可読性の高く、正しく失敗するbuildspecを書く事ができます。

採用

弥生ではエンジニアを募集しています。

herp.careers

参考文献