20m61 / Sonotecture

0 stars 0 forks source link

Next.jsとAWS Lambdaを使ったデプロイと継続的デプロイ (CD) の構築 #19

Open 20m61 opened 1 month ago

20m61 commented 1 month ago

Next.jsを使う場合、API部分(/apiルート)はLambdaにデプロイし、静的なコンテンツ(HTML、JS、CSS)はS3またはCloudFrontにホスティングする形が最適です。これにより、動的なAPI処理と静的コンテンツの処理を分け、コストを最小化できます。


手順1: AWS CDKを使ったNext.jsの構築

Next.jsのアプリケーションをAWSにデプロイするため、Lambdaを使ってAPI部分をホストし、S3で静的コンテンツをホスティングします。

1. CDKの初期設定

  1. AWS CLIのセットアップ
    AWS CLIが未インストールの場合、以下のコマンドでインストールします。

    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
    unzip awscliv2.zip
    sudo ./aws/install
    aws --version
    aws configure
  2. CDKのセットアップ CDKが未インストールの場合、以下のコマンドでインストールします。

    npm install -g aws-cdk
  3. CDKプロジェクトの初期化 プロジェクトディレクトリを作成し、CDKプロジェクトを初期化します。

    mkdir sonotecture-infra
    cd sonotecture-infra
    cdk init app --language typescript

2. AWS Lambda, API Gateway, S3のリソース定義

  1. Lambda関数の定義

Next.jsのAPIルートをAWS Lambdaで処理するため、Lambda関数とAPI Gatewayを定義します。

lib/sonotecture-infra-stack.tsファイルに以下のリソースを定義します。

import * as cdk from 'aws-cdk-lib';
import { Stack, StackProps } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import { Construct } from 'constructs';

export class SonotectureInfraStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Lambda関数の定義
    const apiLambda = new lambda.Function(this, 'ApiLambda', {
      runtime: lambda.Runtime.NODEJS_16_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda'), // lambdaディレクトリにAPIのハンドラコードを配置
    });

    // API Gatewayの作成とLambdaの接続
    const api = new apigateway.LambdaRestApi(this, 'SonotectureApi', {
      handler: apiLambda,
    });

    // S3バケットの作成(Next.jsの静的コンテンツ用)
    const bucket = new s3.Bucket(this, 'SonotectureWebBucket', {
      websiteIndexDocument: 'index.html',
      publicReadAccess: true,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    // Lambda関数がS3にアクセスできるように権限を付与
    bucket.grantReadWrite(apiLambda);
  }
}
  1. Lambda関数のハンドラコード作成

APIルートを処理するためのLambda関数をlambda/ディレクトリに作成します。Next.jsのAPI部分はこのLambdaで処理されます。

lambda/index.js:

exports.handler = async function(event) {
  return {
    statusCode: 200,
    body: JSON.stringify({ message: "Hello from Next.js API running on Lambda!" }),
  };
};

3. Next.jsのビルドと静的コンテンツのデプロイ

Next.jsの静的コンテンツをS3にホスティングするため、Next.jsをビルドしてエクスポートします。

  1. Next.jsのビルド
yarn build
yarn export

このコマンドを実行すると、outディレクトリにNext.jsの静的なHTMLとJSファイルが生成されます。

  1. 静的コンテンツをS3にアップロード

S3バケットに静的コンテンツをアップロードします。

aws s3 sync out/ s3://<bucket-name> --delete

これにより、S3バケット上にNext.jsのフロントエンド部分がホスティングされます。

4. CDKのデプロイ

cdk deployコマンドで全リソースをAWSにデプロイします。

cd sonotecture-infra
cdk deploy

手順2: GitHub Actionsによる継続的デプロイ (CD)

次に、GitHub Actionsを使用して、mainブランチにプッシュされた際に自動的にデプロイが行われる仕組みを設定します。

1. AWSアクセスキーの設定

GitHubのリポジトリにアクセスキーとシークレットキーを設定します。

  1. AWS IAMでアクセスキーとシークレットキーを取得
  2. GitHubリポジトリの設定SecretsActionsNew repository secretで以下のキーを設定
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY

2. GitHub Actionsのワークフローファイル作成

.github/workflows/deploy.ymlを作成し、以下の内容を記述します。

name: Deploy Next.js and API to AWS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '16'

      - name: Install dependencies
        run: yarn install

      - name: Build Next.js project
        run: |
          yarn build
          yarn export

      - name: Deploy static content to S3
        run: aws s3 sync out/ s3://<your-bucket-name> --delete
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      - name: Deploy API to AWS Lambda using CDK
        run: |
          npm install -g aws-cdk
          cd sonotecture-infra
          cdk deploy --require-approval never
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

3. デプロイフロー

  1. コードのプッシュ

    • mainブランチに変更をプッシュすると、GitHub Actionsがトリガーされます。
  2. GitHub Actionsの流れ

    • Next.jsのビルドとエクスポートが行われ、静的ファイルがS3にアップロードされます。
    • Lambdaで動作するAPIがデプロイされます。

まとめ