Aws Code PipelineでReactjs/Nextのデプロイを自動化!ECSへ展開してみました

Aws Code PipelineでReactjs/Nextのデプロイを自動化!ECSへ展開してみました

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CI の構築は色々と選択肢があって迷いますよね。

CircleCI、Jenkins、Aws Code製品と・・。私たちは Aws でワンストップでマネージしたいので、Code Pipeline、CodeBuild、CodeDeploy をフル活用しています。今や三種の神器ですね。

今回は、「Reactjs/NextのCode Pipeline でECSデプロイ自動化」をご紹介します!

Nextjs&ECS の Code Pipeline 開発の流れ

ソースリポジトリは Code Commit でも良いですが、ここはわかりやすく Github にしておきます。(Github の方がメジャーなので…)

  1. Code Pipeline プロジェクトを作成
  2. ソースフェーズに Github を Connect
  3. Code Build の設定
  4. ECS の設定
  5. Dockerfile を作成し Nextjs のビルド疎通
  6. buildspec.yml で Code Build のビルドを定義
  7. imagedefinitions.json でイメージ情報の定義

Code Pipelineプロジェクトを作成

まずは Code Pipeline でプロジェクトを作成します。Aws の管理コンソールへ移動しパイプラインを作成しましょう。

Code Pipeline作成

Code Pipeline のロールを作成もしくは指定します、ここでは、新しいサービスロールを選択し自動的にロール作成をしてもらいます。自分で事前にロールを作成し渡すことも可能ですが、はっきり言って意味ないのでやめましょう。

Pipelineのロール設定

これで Code Pipeline の作成が終わりました。簡単ですね。次は Code Pipeline の各実行工程を設定していきます。

ソースフェーズに Github を Connect

宣告通り Github を利用します。ソースプロバイダーから Github を選択しましょう。

Githubと入力

Github を選択すると、Github へ接続するというボタンが表示れるので、指定のリポジトリへアクセス権限のあるアカウントでコネクションしましょう。

Githubへ接続

成功したら、WebHook でソースコードを調達するリポジトリ及びブランチを指定します。ここで指定したリポジトリとブランチへ、プッシュもしくは PR マージなどされた場合に自動的にデプロイを構築することが可能です。

リポジトリ選択

Code Build の設定

まず環境変数を指定します、これらの値は後ほど Code Build 実行時に buildspec.yml から読み込みます。(後述)

名前
IMAGE_TAGlatest
AWS_DEFAULT_REGIONap-northeast-1
IMAGE_REPO_NAME{ECRのリポジトリ名を指定}
AWS_ACCOUNT_ID{ECRのリポジトリのURLにて確認可}
NODE_ENVproduction
環境変数一覧
Code Buildへ環境変数を追加

ビルド内容を作成していきます。

Code Buildプロジェクトを作成

プロジェクトは設定は下記にしてください。Docker をビルドするので、特権付与をお忘れなく。これを忘れるとビルドフェーズで謎エラーでこけます。

  1. OS に Ubuntu を指定
  2. ランタイムに Standard (標準)を指定
  3. イメージでに aws/codebuild/standard:2.0 を指定
  4. このビルドプロジェクトを使用して Docker イメージをビルドするため特権付与にチェック

ECS の設定

クラスター、サービス名などを指定します。( ECS での解説は割愛します)これで、ビルドが全て完了し ECR へプッシュした後、ECS が latest タグにてイメージを取得しサービスへアサインしてくれます。

Dockerfile を作成し Nextjs のビルド疎通

ではいよいよ、Dockerfile 周りの作成を行います。

Dockerfile

イメージには Nodejs の公式イメージを指定しました。タグでバージョン指定が可能なのでオススメですよ。

FROM node:10.20.1-jessie

# and mount application
RUN mkdir -p /var/www/ragate.co.jp
WORKDIR /var/www/ragate.co.jp
COPY ./ /var/www/ragate.co.jp
RUN npm run build

EXPOSE 3000

ENTRYPOINT ["npm", "run", "start"]

また、package.json はこのようになっていることを想定します。(お好みで調整ください)

{
  "name": "XXXXXX",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "axios": "^0.19.2",
    "classnames": "^2.2.6",
    "dotenv": "^8.2.0",
    "next": "9.3.6",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-gtm-module": "^2.0.8",
    "react-loading": "^2.0.3"
  }
}

buildspec.yml で Code Build のビルドを定義

Github リポジトリのルートディレクトリに buildspec.yml を設置します。Code Pipeline 実行時に自動的に読み込まれます。

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 10  
      docker: 18
  pre_build:
    commands:
      - yarn
      - echo Logging in to Amazon ECR
      - $(aws ecr get-login --no-include-email --region ${AWS_DEFAULT_REGION})
  build:
    commands:
      - yarn build
      - 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 $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG      
  post_build:
    commands:
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
    finally:
      - echo Build completed on `date`

imagedefinitions.json でイメージ情報の定義

Github のルートディレクトリに、imagedefinitions.json ファイルを設置します。イメージと紐付けるコンテナーを定義しましょう。

[
    {
      "name": "target-container-name",
      "imageUri": "${AWS_ACCOUNT_ID}.dkr.ecr.${DEFAULT_REGION_NAME}.amazonaws.com/${REPOSITORY_NAME}:${IMAGE_TAG}"
    }
]

これで概ね設定は終わりです。あとは master ブランチへプッシュしてみてください。Aws Code Pipeline の画面を見るとデプロイが実行されていますよ。カスタムのやり方的次第では、デプロイ後に Aws SNS を実行し Lambda をキックし、Slack へ通知を飛ばすことも可能です。

まとめ

Reactjs/Next だけでなく、Vuejs/Nuxt でに応用の効く Code Pipeline の構築方法をご紹介しました。

基本的にデプロイをローカルから実行するとその人のローカルの環境に依存してバグる可能性が高いので、こう言った共通のデプロイ環境を一つ持っておくのは継続的なインテグレーションで有効です。

是非みなさんも有効活用してみてください。

サーバーレス開発については、お気軽にお問い合わせください。