codepipelineでソース元をBitbucketにしてECSにデプロイする方法


そもそも

ECSの継続的デリバリー(CD)をbitbucketとcodepipelineを使ってやりたい
⇒codepipelineはソース元としてbitbucketを選択することができない
⇒なんとかできたのでメモがてら記録に残すことにしました

2019/02月現在Codepipelineのソース元として選べるのは下記4つだけ

  • AWS CodeCommit
  • Amazon ECR
  • Amazon S3
  • GitHub

Github(あるいはCodeCommit)を使えば以下流れで簡単にできる。(Dockerfile更新)
※【codepipelineのステージ】

  • Source : Github
  • Build : Codebuild
  • Deploy : ECS
  1. GithubにDockerfileをpush
  2. Codepipelineが反応してパイプライン開始
  3. buildが動いてECRにイメージがpushされる
  4. deployが動いてECSでリリースが完了 bitbucketでは2.のところができない。

参考:
https://dev.classmethod.jp/cloud/aws/codepipeline-support-ecs-deploy/
※基本的なところはこの記事が大変参考になりました!

解決方法

ECRプッシュをトリガーにする

ECRにプッシュされたことをトリガーにしたら、実現できた。
CodebuildがBitbucketが選べるのでそれを利用する。

※一時ファイル保存先(アーティファクト)としてS3が必要。適当なS3バケットを事前に用意しておく

  1. Bitbucketにイメージをプッシュ
  2. CodebuildでECRにイメージをプッシュ
  3. ECRをソース元にしたCodepipelineが動く(sourceステージ)
  4. Codebuild(1のとは違うやつ)でECSでデプロイする用のイメージ定義ファイルを作成(buildステージ)
  5. 3のイメージ定義ファイルを元にECSでデプロイ(deployステージ)

※【codepipelineのステージ】

  • Source : ECR
  • Build : Codebuild
  • Deploy : ECS(fargate構成)

1. CodebuildでECRにイメージをプッシュするまで

Codebuildの設定(ECRプッシュ用)

  • ソースプロバイダは「BitBucket」
  • Webhook(コードの変更がこのレポジトリにプッシュされるたびに再構築する)の設定をON
  • Buildspecファイル名はデフォルトの「buildspec.yml」
  • 環境変数は下記を設定
名前 入力
AWS_DEFAULT_REGION ap-northeast-1 PLAINTEXT
IMAGE_REPO_NAME codebuild PLAINTEXT
IMAGE_TAG latest PLAINTEXT
AWS_ACCOUNT_ID *** PLAINTEXT
  • アーティファクトの設定で事前に作成したS3を設定する。

  • Bitbucketのレポジトリ構成

$ tree .
.
├ buildspec.yml
└ Dockerfile
  • buildspec.yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
      - REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo "[{\"name\":\"${IMAGE_REPO}\",\"imageUri\":\"${REPOSITORY_URI}:${IMAGE_TAG}\"}]" > imageDetail.json
artifacts:
  files:
    - imageDetail.json

※imageDetail.jsonが先ほど設定したS3に保存される。

  • Dockerfile
FROM centos:centos7
RUN yum install -y httpd && date >> /var/www/html/index.html
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

この状態であとはgit pushをすればCodebuildが動いてECRにプッシュされる。

ここまでCodepipeline関係ない。


2. ECRをソース元にしたCodepipelineが動く(sourceステージ)

Codepipelineのアーティファクトストアは事前に作成したS3を選択しておく。

  • ソースステージの設定


3. Codebuild(1のとは違うやつ)でECSでデプロイする用のイメージ定義ファイルを作成(buildステージ)

  • ビルドステージの設定

  • Codebuildの設定(デプロイ用)

  • ソースプロバイダはなし。設定なしでOKです。

  • Buildspecは「ビルドコマンドの挿入」から直接入力
    ⇒Codepipelineのソース元がECRだとCodebuildで設定したソースが反応しません。そのためソースプロバイダも設定していません。

  • 環境変数は下記を設定

名前 入力
AWS_DEFAULT_REGION ap-northeast-1 PLAINTEXT
SERVICE_NAME test PLAINTEXT
IMAGE_TAG latest PLAINTEXT
AWS_ACCOUNT_ID *** PLAINTEXT
  • アーティファクトの設定で事前に作成したS3を設定する。

  • ビルドコマンド

version: 0.2

phases:
  build:
    commands:
       - sudo apt-get update -y
       - sudo apt-get install -y jq
       - REPOSITORY_URI=$(cat imageDetail.json | jq .ImageURI | sed 's/"//g' | sed -E 's/@.*//g')
       - echo $REPOSITORY_URI
       - IMAGE_TAG=$(cat imageDetail.json | jq .ImageTags[0] | sed 's/"//g')
       - echo $IMAGE_TAG
  post_build:
    commands:
       - printf '[{"name":"'$SERVICE_NAME'","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

4. 3のイメージ定義ファイルを元にECSでデプロイ(deployステージ)


以上で設定は完了。
あとはBitbucketにDockerfileをpushすれば自動で全部走る。

※ECR更新に反応してくれない場合はCloudTrailの証跡作成が必要。
https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/cloudtrail-create-a-trail-using-the-console-first-time.html

最後に

AWSサポート様いわく、CodepipelineでもBitbucketをサポートするよう動いてるみたいなので、
楽しみにしてます。
そしたら上記のような面倒くさいことをしなくて済みます。

おかしな点、不足点、不明点などがありましたらコメントいただけると嬉しいです。