飽き性の頭の中

今は福岡でWeb開発をしている26歳。単なる文字の記録。

CodePipeline + ECRを使ってDockerイメージをElastic Beanstalkに自動デプロイできるようにした話【CI/CD】

f:id:tawachan39:20200116235225j:plain

こんにちは、たわです。AWSでElastic Beastalkでワークフローを整理したのでその時のメモです。

ゴールとしては、

  • GitHubで変更をプッシュしたら
  • 自動でDockerイメージがビルドされ
  • Amazon ECR上にプッシュされて
  • それがElastic Beastalk上にデプロイされる

ワークフローを作ることです。

Elastic Beastalkの環境構築

Elastic Beastalkを立ち上げます。

アプリケーションの作成

まずはコンソールからアプリケーションの作成をします。

f:id:tawachan39:20200116224045j:plain
アプリケーションの作成を押す

f:id:tawachan39:20200116224119j:plain
アプリケーション名を入力

そうすると、空のアプリケーションができあがります。

f:id:tawachan39:20200116224138j:plain
空のアプリケーションができる

環境の作成

次はアプリケーションの中に環境を作成していきます。

  • development
  • staging
  • production

といったように環境ごとに作り分けるという思想なんだと思います。

  • backend
  • frontend

というように分けてもいいのかもしれません。管理しやすいようにすれば良いと思います。

ウェブサーバー環境を選択

  • ウェブサーバー環境
  • ワーカー環境

がありますが、今回はウェブサーバー環境を選択します。

f:id:tawachan39:20200116224446j:plain
ウェブサーバー環境

プラットフォームはDockerを選択

インスタンスの中で何を稼働させるかを選択することができます。

  • Node.js
  • Go
  • Python

といったランタイムを選ぶこともできますが、今回はDockerを選択します。

f:id:tawachan39:20200116224517j:plain
Docker

アプリケーションコードはサンプルのまま

アプリケーションコードはサンプルがデフォルトだと思いますがそのままにします。

あとでデプロイフローは整えそのときに自分のコードが展開されるようにするのでとりあえずこれで良いです。

f:id:tawachan39:20200116224710j:plain
サンプルコードを選択

その他オプション設定はここで

  • インスタンスの数
  • セキュリティグループ
  • VPC
  • ロードバランサー

などなど設定する場合は「より多くのオプションの設定」を押して詳細設定画面に遷移しましょう。

f:id:tawachan39:20200116224906j:plain
オートスケーリング等をするなら絶対必要

数分待てば起動完了

数分待てば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となります。

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/single-container-docker.html#single-container-docker.test-remote

上記公式サイトを参考にすると下記のような設定ファイルです。

{
  "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を設定します。

パイプラインの作成

まずはパイプラインの作成をします。

f:id:tawachan39:20200116231724j:plain
パイプラインの作成

f:id:tawachan39:20200116231745j:plain
名称等を設定

ソースステージを追加する

データソースを設定します。ここではGitHubを設定します。

f:id:tawachan39:20200116231846j:plain
ここではGitHub

自動デプロイのトリガーにするブランチを決めて作っておくと良いでしょう。

ビルドステージを追加する

次にデータソースをもとにどのようにビルドするのかの設定です。

ここでは先ほどCodeBuildで作成したプロジェクトを指定するだけとなります。

f:id:tawachan39:20200116232039j:plain
先程作ったものを指定

デプロイステージを追加する

最後にデプロイステージの追加です。最初に作成したElastic Beastalkを指定しましょう。

f:id:tawachan39:20200116232128j:plain
Elastic Beanstalkを選択

f:id:tawachan39:20200116232150j:plain
アプリケーションと環境を選択

確認して良さそうであればパイプラインの作成は完了です。

f:id:tawachan39:20200116232229j:plain
完了

Elastic BeanstalkにECRアクセスの権限を付与

デフォルトだとElastic Beastalkが各EC2に設定するロールではECRにアクセスできないはずです。

Elastic BeanstalkがDockerのプライベートレジストリにアクセスする場合、認証が必要なので、先ほどのDockerrun.aws.jsonAuthenticationを追加する必要があると書いてあるものがありますが、AWS ECRの場合はその限りではありません。同じAWSのサービスなので適切なロールを与えて上げれば大丈夫です。

IAMインスタンスプロフィールを確認

まず、Elastic BeanstalkについているIAMプロフィールを確認しましょう。

f:id:tawachan39:20200116233427j:plain
IAMプロフィールを確認

ECRへのRead権限を付与

あとは確認したプロフィールをIAMのコンソール画面から編集します。

ロールを選択して、AmazonEC2ContainerRegistryReadOnlyポリシーをアタッチすれば大丈夫なはずです。

f:id:tawachan39:20200116233618j:plain
ECRへのRead権限を付与

まとめ

上記をやってうまく行っていればパイプラインがグリーンマークで表示されるでしょう。

f:id:tawachan39:20200116232250j:plain
オールグリーン

先ほどこの設定をしたので備忘録的に書きました。基礎的なことですが数日後には忘れているので困らないように。