そもそも
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
 
- GithubにDockerfileをpush
 - Codepipelineが反応してパイプライン開始
 - buildが動いてECRにイメージがpushされる
 - deployが動いてECSでリリースが完了
bitbucketでは2.のところができない。 
参考:
https://dev.classmethod.jp/cloud/aws/codepipeline-support-ecs-deploy/
※基本的なところはこの記事が大変参考になりました!
解決方法
ECRプッシュをトリガーにする
ECRにプッシュされたことをトリガーにしたら、実現できた。
CodebuildがBitbucketが選べるのでそれを利用する。
※一時ファイル保存先(アーティファクト)としてS3が必要。適当なS3バケットを事前に用意しておく
- Bitbucketにイメージをプッシュ
 - CodebuildでECRにイメージをプッシュ
 - ECRをソース元にしたCodepipelineが動く(sourceステージ)
 - Codebuild(1のとは違うやつ)でECSでデプロイする用のイメージ定義ファイルを作成(buildステージ)
 - 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をサポートするよう動いてるみたいなので、
楽しみにしてます。
そしたら上記のような面倒くさいことをしなくて済みます。
おかしな点、不足点、不明点などがありましたらコメントいただけると嬉しいです。


