Chapter 19

CircleCI を使った自動デプロイ

それでは最後に CircleCI を使って、 PR が main ブランチに merge されたタイミングで、 image を build して ECR に push し、その image を用いて ECS へのデプロイが行われるようにしていきます。

  1. main ブランチへの merge でテストが流れるようにする
  2. テストがパスしたら image を build し、ECR に push する
  3. ECR に image が push されたら、 ECS にデプロイする

という流れになります。

1.main ブランチの merge でテストが流れるようにする

まずは別ブランチを切って、そのブランチで .circleci/config.yml に以下を追加します。

...
workflows:
  ...
  test_and_deploy:
    jobs:
      - test_backend:
          filters:
            branches:
              only: main
      - test_frontend:
          filters:
            branches:
              only: main

追加したら PR を作成します。
CI がパスしたら、 main に merge します。

CircleCI を確認して、テストが流れていたら OK です。

2.テストがパスしたら image を build し、push する

CircleCI でAWS ECR への push や ECS へのデプロイをするに当たって、 CircleCI Orbs を使います。
詳細な説明は公式をご確認いただければと思いますが、 私の理解では、AWS へデプロイするのに必要な(書かないといけない) command や job の定義がパッケージ化されていて、利用者は command や job を自身で書かなくても、orbs を定義するだけで使えるようになり、容易にデプロイ等ができるようになるというメリットがあると思います。

ということで、 image の build と push を進めていきます。

まずは CircleCI と AWS を連携させるために AWS IAM で CircleCI 用のユーザーを作成し、そのユーザーの「アクセスキー」と「シークレットアクセスキー」を CircleCI に登録します。

IAM の設定

IAM のダッシュボードを開き、 グループをクリックします。
そして [新しいグループの作成] ボタンをクリックします。

そして、任意のグループ名を入力し、次のステップに進みます。

「ポリシーのアタッチ」では、以下の2つを選択します。

  • AmazonEC2ContainerRegistryFullAccess
  • AmazonEC2ContainerServiceFullAccess

確認画面で、[グループの作成] をクリックし、グループを作成します。

次に、ユーザーを作成します。
[ユーザーを追加] ボタンをクリックします。

「ユーザーの詳細の設定」で、任意のユーザー名を入力し、「プログラムによるアクセス」を選択し、次のステップに進みます。

「アクセス許可の設定」で、先ほど作成したグループをチェックし、次のステップに進みます。

タグの追加画面ですが、任意のタグを追加します。(しなくても OK です。)
確認画面に進み、[ユーザーの作成] ボタンをクリックします。

成功メッセージが表示されれば OK です。

この画面で表示される アクセスキーIDシークレットアクセスキー を必ず控えてください。

以上で、 IAM の設定は完了です。

環境変数の確認

CircleCI での設定において、 アクセスキーIDシークレットアクセスキー 以外に、

  • アカウントID
  • アカウントURL
  • リージョン

が必要です。

上記3つの値は ECR の URI を確認すればわかるので、ECR の URI を確認します。
例えば、URI が以下だった場合は、

1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/zenn-app-backend
アカウントID: 1234567890
アカウントURL: 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com
リージョン: ap-northeast-1

です。

それでは、CircleCI の設定に進みます。

CircleCI の設定

CircleCI の projects から該当する project 名をクリックします。

[Project Settings] をクリックします。

サイドメニューから [Environment Variables] をクリックします。

[Add Variable] をクリックし、環境変数を定義します。
ここでは 「環境変数の確認」 で確認した値をセットしてください。

キー
AWS_ACCOUNT_ID 1234567890
AWS_ACCESS_KEY_ID アクセスキーID
AWS_SECRET_ACCESS_KEY シークレットアクセスキー
AWS_ACCOUNT_URL 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com
AWS_REGION ap-northeast-1

全ての環境変数をセットしたら完了です。

.circleci/config.yml の追加

.circleci/config.yml に以下のように orbs, jobs, workflow を追加してください。

別ブランチを切っても、 main ブランチのままでもどちらでも結構です。
別ブランチで切った場合は、 main に merge するタイミングで、 追加した workflow が実行されますし、 main のままの場合はリモートに push したタイミングで実行されます。
説明自体は簡略化のために main のまま追加した体で進めます。

 version: 2.1

+orbs:
+  aws-ecr: circleci/aws-ecr@6.12.2
+
 jobs:
   test_backend:
     docker:
@@ -92,6 +95,30 @@ jobs:
           command: npm run test
           working_directory: ~/repo/frontend

+  build_and_push_image_backend:
+    machine:
+      image: ubuntu-1604:201903-01
+    steps:
+      - checkout
+      - aws-ecr/build-and-push-image:
+          account-url: AWS_ACCOUNT_URL
+          repo: "zenn-app-backend"
+          region: AWS_REGION
+          tag: "${CIRCLE_SHA1}"
+          path: ./backend/
+
+  build_and_push_image_frontend:
+    machine:
+      image: ubuntu-1604:201903-01
+    steps:
+      - checkout
+      - aws-ecr/build-and-push-image:
+          account-url: AWS_ACCOUNT_URL
+          repo: "zenn-app-frontend"
+          region: AWS_REGION
+          tag: "${CIRCLE_SHA1}"
+          path: ./frontend/
+
 workflows:
   version: 2
   test:
@@ -114,3 +141,17 @@ workflows:
           filters:
             branches:
               only: main
+      - build_and_push_image_backend:
+          requires:
+            - test_frontend
+            - test_backend
+          filters:
+            branches:
+              only: main
+      - build_and_push_image_frontend:
+          requires:
+            - test_frontend
+            - test_backend
+          filters:
+            branches:
+              only: main

config.yml を追加して、コミットを積んだら push します。
push したら、 CircleCI を開き、以下のように workflow が表示されていることを確認します。

AWS への連携や image の build、 ECR への push が成功すれば以下のような表示になります。

成功したら、実際に ECR に image が push されているかを確認します。

3. ECR に image が push されたら、 ECS にデプロイする

.circleci/config.yml の追加

.circleci/config.yml に以下のように orbs, jobs, workflow を追加してください。

 orbs:
   aws-ecr: circleci/aws-ecr@6.12.2
+  aws-ecs: circleci/aws-ecs@1.3.0

 jobs:
   test_backend:
@@ -155,3 +156,24 @@ workflows:
           filters:
             branches:
               only: main
+      - aws-ecs/deploy-service-update:
+          requires:
+            - build_and_push_image_frontend
+            - build_and_push_image_backend
+          family: "zenn-app-task-backend"
+          service-name: "zenn-app-service-backend"
+          cluster-name: "zenn-app-cluster"
+          container-image-name-updates: "container=zenn-app-container-backend,tag=${CIRCLE_SHA1}"
+          filters:
+            branches:
+              only: main
+      - aws-ecs/deploy-service-update:
+          requires:
+            - build_and_push_image_frontend
+            - build_and_push_image_backend
+          family: "zenn-app-task-frontend"
+          service-name: "zenn-app-service-frontend"
+          cluster-name: "zenn-app-cluster"
+          container-image-name-updates: "container=zenn-app-container-frontend,tag=${CIRCLE_SHA1}"
+          filters:
+            branches:
+              only: main

config.yml を追加して、コミットを積んだら push します。
CircleCI に aws-ecs/deploy-service-update の項目が追加されていることを確認します。

次に、ECS のクラスターのダッシュボードを確認します。
新しい image でデプロイされ、一時的にタスクが4つになります。

ロードバランサーによるヘルスチェックが成功し、新タスクに問題ないことが分かると、旧タスクは自動で停止されます。

https://hibriiiiidge.com にアクセスし、意図通りの挙動をすることを確認してください。
今回は画面に表示されるコードを変えてないので、変化が分からないのですが、是非、画面に表示されるコードを変えて、デプロイしてみてください。