見出し画像

AWSで自作Webアプリのリリースを自動化した話

1. はじめに

以下の記事で共有した2023年のGWに作成した自作Webアプリのリリースの自動化を行いました。
自分の今後へのメモにもなるので記事化してみました。

上記の記事で紹介した自作Webアプリ
「両親、友人、彼氏・彼女へのプレゼントをおすすめしてくれるアプリ」

https://github.com/Kedaiman/recommend-app

AWS構成はこちら
ECS上のFargateで動作させている構成になります

自作WebアプリのAWS構成

2. なぜリリースの自動化を行うのか

デプロイの自動化を実施するまでは、以下のリリース手順を手作業で実施していました。

  1. ローカルの環境でDockerイメージをビルドして生成

  2. 生成したDockerイメージをECRにプッシュ

  3. 新しいDockerイメージのリビジョンを指定したタスク定義の作成

  4. サービスの更新

手順1-2についてはローカルの開発端末で実施します

# 1. ローカルのプロジェクトをビルドしてイメージ生成
docker build -t my-image .

# 2-1. AWSのECRのタグ付け
docker tag my-image:latest <account-id>.dkr.ecr.<region>.amazonaws.com/<repository-name>:<tag>
 
# 2-2. ECRにログインする
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com

# 2-3. DockerイメージをECRにプッシュする
docker push <account-id>.dkr.ecr.<region>.amazonaws.com/my-docker-repo:latest

手順3-4ではAWSのコンソールのECS/タスク定義で新しいリビジョンを作成した上で、「サービスを更新」ボタンを押してタスク定義の新しいリビジョンを指定した上でリリース。

手動の手順で行っても良いのですが、何度も行っていると流石にめんどくさくなってきたので、Github上のmainブランチにマージしたタイミングで自動でリリースをできるようにしたいと思いました。

3. 事前学習

今回の自動化を実施する前に以下のudemy講座で勉強しました。

AWSで学ぶ!Dockerコンテナ・CI/CDパイプライン入門
https://www.udemy.com/course/dockercicd/

個人的な本講座の感想としてはちょこちょこハンズオンでつまづくことになるので、ハンズオンを全部実施しなくても、流し見してイメージを掴むだけでも良い気がしました。

4. 自動化手順

自動化にはAWSサービスのCodePipelineを利用します。

4.1 buildspec.ymlの作成

buildspec.ymlとは、CodePipelineのCodeBuild上でビルド実行時に実行するコマンドを記述したYAML形式のファイルになります。こちらのファイルで「2. なぜリリースの自動化を行うのか」で紹介した手順を自動で実施するための設定を記載する必要があります。

version: 0.2

env:
  parameter-store:
    APP_ID: 'パラメータストアの名前を指定'

phases:
  pre_build:
    commands:
      - aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com
      - REPOSITORY_URI=<account-id>.dkr.ecr.<region>.amazonaws.com/my-docker-image
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)

  build:
    commands:
      - npm i
      - echo NUXT_APP_ID=$APP_ID > .env
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG

  post_build:
    commands:
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - printf '[{"name":"recommend-app","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json

artifacts:
  files: imagedefinitions.json

envではAWS System Managerで管理している情報にアクセスし、その情報を環境変数に設定しています。
pre_buildではECRへのログインやリポジトリURIおよびイメージタグの生成を実施しています。CODEBUILD_RESOLVED_SOURCE_VERSIONはビルドのソースコードのバージョンの識別子になります。

buildではnpmインストール、環境変数ファイルの.envファイルの作成、Dockerビルド、ECRのタグ付けなどを実施しています。
post_buildではDockerイメージをECRにプッシュした上で、CodeBuildの成果物となるimagedefinitions.jsonを作成しています。

imagedefinitions.jsonについてはECSにDockerイメージをデプロイする際の設定ファイルになります。
詳細については以下を参照してください

4.2 パイプラインの作成

AWSのCodePipelineに遷移して、「パイプラインの作成」をクリック。

パイプライン作成画面 (2023/5/21時点)

パイプライン名は適当に設定し、サービスロールについては「新しいサービスロール」を指定します。そのようにすることでここで作成するパイプラインが必要なポリシーを自動でアタッチしてくれます。
次に進むとソースステージを追加する画面に遷移します。

ソースステージ設定画面 (2023/5/21時点)

ここでは実際にソースコードを管理しているサービスを指定します。
私はGithubを使用しているので、「Github (バージョン2)」を指定しました。
ここで「Githubに接続する」ボタンを押下しGithubのプロジェクトとのコネクションを確立した上で、今回のビルド対象のブランチを指定します。(今回はmainブランチにマージされたタイミングでの自動リリースとしたかったため、ブランチ名はmainブランチを指定しました)
次に進むとビルドステージを設定する画面に遷移します。

ビルドステージ設定画面 (2023/5/21時点)

ビルドステージ設定については、CodeBuildを使用するため、「AWS CodeBuild」を指定した上でプロジェクト名は適当に設定します。
次に進むとデプロイステージを設定する画面に遷移します。

デプロイステージ設定画面 (2023/5/21時点)

デプロイプロバイダーには「Amazon ECS」を設定しました。
「3. 事前学習」で紹介したudemyの講座では「Amazon ECS(ブルー/グリーン)」を指定した上で ブルー/グリーンデプロイを実現していました。
今回自分はそこまでする必要がないかなと思ったので、デプロイプロバイダーには「Amazon ECS」を設定しました。
今回ここのデプロイプロバイダーによって、用意する設定ファイルなども異なるので注意が必要です。

ブルー/グリーンデプロイについては以下参照

ここで既に作成済みのECSクラスターやサービスを指定すると設定は終わりです。

4.3 CodeBuildのロールにアタッチされている許可ポリシーを修正

4.2までで動作確認したところ、CodeBuildの権限が足りずにビルドが失敗したので、自動で作成されているCodeBuildのロールに対して必要なポリシーをアタッチします。

以下の権限をアタッチしました。
・AmazonEC2ContainerRegistryPowerUser
 → ECRへプッシュするための権限
・パラメータストア参照権限ポリシー (自作ポリシー)
 → パラメータストアで設定しているパラメータを参照させる権限を追加する必要あり
 ※以下を参考にして自作ポリシーを作成してアタッチ

4.3 動作確認

動作確認を実施します。
mainブランチに対して修正をマージした際にCodePipelineが動作し、自動でリリースされるかチェック
・CodePipelineが全て成功するか
・ECRに新しいイメージがプッシュされているか
・ECSのタスク定義が新しいリビジョンになっているか
・リリース後動作確認

全て問題なしだったので、成功!

5. おわりに

今回は自作Webアプリのリリースを自動化してみました。
次はテストの自動化なども行っていく予定です。(自作Webアプリなのでテストコードが全くないのでまずはそこを作るところから必要)
ECSなどを使用していると結構お金がかかってしまうので、ある程度お勉強が終わったらもっと安い環境などに移行する必要がありそう。。。



この記事が気に入ったらサポートをしてみませんか?