CodePipeline + ECRを使ってDockerイメージをElastic Beanstalkに自動デプロイできるようにした話【CI/CD】
Table Of Contents
こんにちは、たわです。AWS で Elastic Beastalk でワークフローを整理したのでそのときのメモです。
ゴールとしては、
- GitHub で変更をプッシュしたら
- 自動で Docker イメージがビルドされ
- Amazon ECR 上にプッシュされて
- それが Elastic Beastalk 上にデプロイされる
ワークフローを作ることです。
Elastic Beastalk の環境構築
Elastic Beastalk を立ち上げます。
アプリケーションの作成
まずはコンソールからアプリケーションの作成をします。
そうすると、空のアプリケーションができあがります。
環境の作成
次はアプリケーションの中に環境を作成していきます。
- development
- staging
- production
といったように環境ごとに作り分けるという思想なんだと思います。
- backend
- frontend
というように分けてもいいのかもしれません。管理しやすいようにすればよいと思います。
ウェブサーバー環境を選択
- ウェブサーバー環境
- ワーカー環境
がありますが、今回はウェブサーバー環境を選択します。
プラットフォームは Docker を選択
インスタンスの中で何を稼働させるかを選択できます。
- Node.js
- Go
- Python
といったランタイムを選ぶこともできますが、今回は Docker を選択します。
アプリケーションコードはサンプルのまま
アプリケーションコードはサンプルがデフォルトだと思いますがそのままにします。
あとでデプロイフローは整えそのときに自分のコードが展開されるようにするのでとりあえずこれでよいです。
その他オプション設定はここで
- インスタンスの数
- セキュリティグループ
- VPC
- ロードバランサー
などなど設定する場合は「より多くのオプションの設定」を押して詳細設定画面に遷移しましょう。
数分待てば起動完了
数分待てば Elastic Beanstalk に関連する、EC2 やその他必要なものが立ち上がり準備完了となるはずです。
CodeBuild の設定
次に GitHub から自動で Docker イメージをビルドして ECR にプッシュする流れを設定する必要があります。
CodePipeline でデプロイまでのフローを設定する前に必要です。
ここの詳細に関しては別記事で紹介しているのでそちらを参照してください。今回は当記事との差分だけ紹介します。
buildspec.yml
を修正
CodePipeline では後続のタスクに情報を引き継ぐことができます。
なので、CodeBuild の設定ファイル(buildspec.yml
)を修正して、ビルド後にデプロイに必要な情報を引き継げるようにします。
元々の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)
- AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
- REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- echo $IMAGE_REPO_NAME:$IMAGE_TAG
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG -f $DOCKERFILE .
- 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 to $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG ...
- DOCKER_URL=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
- docker push $DOCKER_URL
Elastic Beastalk ではDockerrun.aws.json
が必要
Elastic Beanstalk の設定ファイルはDockerrun.aws.json
となります。
上記公式サイトを参考にすると次のような設定ファイルです。
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "username/beanstalk-flask",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "5000"
}
]
}
なのでこれに準じたファイルを作成し引き継ぎます。
実際の修正箇所
先ほどのbuildspec.yml
を修正してこうなります。
version: 0.2
phases:
install:
runtime-versions:
docker: 18
pre_build:
commands:
## ... 省略
build:
commands:
## ... 省略
post_build:
commands:
## ... 省略
## ↓ 追加
- printf '{"AWSEBDockerrunVersion":"1","Image":{"Name":"%s","Update":"true"},"Ports":[{"ContainerPort":"%s"}]}' $DOCKER_URL $PORT > Dockerrun.aws.json
## ↓ 追加
artifacts:
files:
- Dockerrun.aws.json
※ポート番号は CodeBuild の環境設定から適宜渡すようにしてください。
CodePipeline の設定
CodeBuild の設定ができたら CodePipieline を設定します。
パイプラインの作成
まずはパイプラインの作成をします。
ソースステージを追加する
データソースを設定します。ここでは GitHub を設定します。
自動デプロイのトリガーにするブランチを決めて作っておくとよいでしょう。
ビルドステージを追加する
次にデータソースをもとにどのようにビルドするのかの設定です。
ここでは先ほど CodeBuild で作成したプロジェクトを指定するだけとなります。
デプロイステージを追加する
最後にデプロイステージの追加です。最初に作成した Elastic Beastalk を指定しましょう。
確認して良さそうであればパイプラインの作成は完了です。
Elastic Beanstalk に ECR アクセスの権限を付与
デフォルトだと Elastic Beastalk が各 EC2 に設定するロールでは ECR にアクセスできないはずです。
Elastic Beanstalk が Docker のプライベートレジストリにアクセスする場合、認証が必要なので、先ほどのDockerrun.aws.json
にAuthentication
を追加する必要があると書いてあるものがありますが、AWS ECR の場合はその限りではありません。同じ AWS のサービスなので適切なロールを与えて上げれば大丈夫です。
IAM インスタンスプロフィールを確認
まず、Elastic Beanstalk についている IAM プロフィールを確認しましょう。
ECR への Read 権限を付与
あとは確認したプロフィールを IAM のコンソール画面から編集します。
ロールを選択して、AmazonEC2ContainerRegistryReadOnly
ポリシーをアタッチすれば大丈夫なはずです。
まとめ
上記をやってうまく行っていればパイプラインがグリーンマークで表示されるでしょう。
先ほどこの設定をしたので備忘録的に書きました。基礎的なことですが数日後には忘れているので困らないように。