Circle CI + AWS + Dockerでデプロイを自動化する

今回はタイトルの通り、Circle CI + AWS + Dockerの組み合わせで簡単にサービスのデプロイを自動化した話をします。

弊社サービスWorkinGoodではGItHub flowを採用しており、masterへマージした後に自動的にElastic Beanstalkへ新しいバージョンを作るところまで行っています。依存サービスとの関係もありデプロイするタイミングはこちらが手動でAWSGUI上から行っています。

また、弊社では開発環境構築にDockerを使っていますが、本番環境へのデプロイにも使用しています。

http://blog.matchingood.com/entry/2016/11/11/145246blog.matchingood.com

これを実現するために具体的には以下のものを使っています。

  • GitHub
  • Circle CI
  • Docker
  • AWS Elastic Container Registry (Docker registry)
  • AWS Elastic Beanstalk

この中でもデプロイを圧倒的に簡単にしているのがDockerとElastic Beanstalkの組み合わせです。Elastic BeanstalkとはAWSが提供しているサービスの一つで、あらかじめ用意しておいた環境定義ファイルによって自動的にAuto Scalingとデータベースを構築してくれるサービスです。

こちらに簡単な説明があったので見てみるといいと思います。

dev.classmethod.jp

かなりお手軽にこの仕組みを作ることができるので簡単に手順を示していきたいと思います。

circle.yml

最初にcircle.ymlにどのように書けばいいかの例です。

machine:
    timezone:
        Asia/Tokyo

    services:
        - docker
dependencies:
    pre:
        - sudo pip install --upgrade awscli

deployment:
    production:
        branch: master
        commands:
            - ./deploy.sh $CIRCLE_SHA1

今回の話に関係のあるところだけ書きました。

deploymentにbranchをmasterに指定することでmasterブランチのCIが通った時にcommands以下が実行されます。Circle CI内ではGitHubのコミットIDが$CIRCLE_SHA1という変数に入っています。

aws-cliを使用するために$AWS_ACCESS_KEY_IDと$AWS_SECRET_ACCESS_KEYの環境変数を設定する必要がありますが、セキュリティ上の問題からバージョン管理に含めずにCircle CI上のUIから設定します。

deploy.sh

SHA1=$1
DOCKERRUN_FILE=$SHA1-Dockerrun.aws.json
EB_BUCKET= # Elastic Beanstalkのバージョンファイルが入るS3のバケット名

aws ecr get-login | bash

docker build -t {AWS ID}.dkr.ecr.us-east-1.amazonaws.com/{リポジトリ名}:$SHA1 .
docker push {AWS ID}.dkr.ecr.us-east-1.amazonaws.com/{リポジトリ名}:$SHA1

sed "s/<tag>/$SHA1/" < Dockerrun.aws.json > $DOCKERRUN_FILE

aws s3 cp $DOCKERRUN_FILE s3://$EB_BUCKET/$DOCKERRUN_FILE

aws elasticbeanstalk create-application-version\
  --application-name application \
  --version-label $SHA1 \
  --source-bundle S3Bucket=$EB_BUCKET,S3Key=$DOCKERRUN_FILE

Elastic Beanstalkのバージョンはただのjsonファイルで管理されているのであらかじめDockerrun.aws.jsonという名前で以下のファイルを用意しています。

{
    "AWSEBDockerrunVersion": "1",
    "Image" : {
        "Name" : "{AWS ID}.dkr.ecr.us-east-1.amazonaws.com/{リポジトリ名}:<tag>"
    },
    "Ports" : [{ "ContainerPort": "80" }]
}

やっていることの流れとしては

  • aws-cliでログイン
  • Dockerコンテナをビルド
  • Dockerコンテナをpush
  • バージョンファイルをS3に上げる
  • Elastic Beanstalkに新しいバージョンを作る

という感じです。 ここまで行えばElastic Beanstalkに新しいバージョンが作成されているのがわかると思います。

注意点

Circle CI用に適切な権限を持ったIAMを用意する必要があります。以下の操作ができるようにIAMを作りましょう。

  • S3のバージョンファイルが入るバケットへのアップロード
  • Docker Container Registryへのpush
  • Elastic Beanstalkのバージョンの作成

まとめ

簡単にデプロイの自動化ができそうなのがわかっていただけたと思います。弊社のような小規模のチームでの開発では自動化できるところは自動化を進めて効率を高める必要があります。 このようなモダンな仕組みもすべてアルバイトエンジニアによって構築されています。プログラミング初心者の方はこのような新しい仕組みを学ぶことができ、実力のある人はDevOpsをさらに磨き上げることもできる職場です。