Next.jsで作成したWebアプリをAppRunnerで動かす際のテンプレート

Page content

Next.jsで作成したWebアプリをAppRunnerで動かす際のテンプレート

Next.jsで作成したWebアプリをAppRunnerで動かす際のテンプレートです。以下の構成を想定しています。

なぜAppRunnerを利用するのか?

AWS環境でNext.jsで作成したWebアプリを動かす際にはAWS Amplifyを利用することが多いと思いますが、閉域網などでなるべくシンプルな構成で動かしたい場合には、AppRunnerを利用するのが便利です。本テンプレートはそのような環境でNext.js(で作成したWebアプリ)を動かすための最小限の構成を提供します。

なお、本テンプレートのAppRunnerはVPCを指定しないため、閉域網で利用する際にはCDK部分の変更が必要です。また、認証にCognitoを利用していますが、CognitoはVPC Endpointを利用できないため、完全に閉域内での通信にならない点は注意してください。

完全なコードは以下を参照してください。

デプロイ手順

  1. Cognitoのユーザープールを作成する
  2. Cognitoのユーザープールに、アプリクライアントを作成する
  3. aws-exports.jsを準備する
  4. CDKでデプロイする

Cognitoのユーザープールを作成する

AWSのコンソールからCognitoのユーザープールを作成します。

Cognitoのユーザープールに、アプリクライアントを作成する

Cognitoのユーザープールに、アプリクライアントを作成します。

aws-exports.jsを準備する

aws-exports.jsを作成します。以下のような内容になります。

const awsmobile = {
    aws_project_region: 'ap-northeast-1',
    aws_cognito_region: 'ap-northeast-1',
    aws_user_pools_id: '[作成したユーザープールのIDで置き換えてください]',
    aws_user_pools_web_client_id: '[作成したアプリクライアントのIDで置き換えてください]',
};

export default awsmobile;

aws-exports.jsは以下に配置します。

  • app/nextjs-on-apprunner-demo/src/aws-exports.js

CDKでデプロイする

CDKを使用して、AppRunnerにデプロイします。

cd cdk
AWS_DEFAULT_REGION=ap-northeast-1 cdk synth # CFnが意図した通り出力されることを確認します。
AWS_DEFAULT_REGION=ap-northeast-1 cdk diff # 差分を確認します。
AWS_DEFAULT_REGION=ap-northeast-1 cdk deploy

補足事項

Amplify UIのログイン画面利用する場合は、ClientComponentを使用する必要がある

Amplify UIのAuthenticatorを使用する場合、ServerComponentではなくClientComponentを使用する必要があります。

ServerComponentでCognitoの認証情報を取得する場合は、AmplifyのSSRを使用を指定する必要がある

ServerComponentで(Amplify UIのログイン画面利用を利用してログインをした)Cognitoの認証情報を取得する場合は、Amplifyのconfigureで、ssr=trueを指定する必要があります。これにより、認証情報がcookieに保存されるようになります。

Amplify.configure({ ...awsExports }, { ssr: true }); // ssrをtrueにすることで、Cognitoの認証情報をSSRで取得できるようにします。

Amplify.jsをServerComponentで使用する場合は、Next.js Adapterを導入する必要がある

ServerComponentでAmplify.jsを使用する場合は、Next.js Adapterを導入する必要があります。

npm add aws-amplify @aws-amplify/adapter-nextjs

今回の環境では、Next.js AdapterのrunWithAmplifyServerContextをcookieに保存された認証情報と共に呼び出し、SSR版のAmplify.js関数を呼び出します。

import { getCurrentUser } from 'aws-amplify/auth/server';
import { fetchAuthSession } from 'aws-amplify/auth/server';
import { fetchUserAttributes } from 'aws-amplify/auth/server';

export const { runWithAmplifyServerContext } = createServerRunner({
    config,
});

[省略]

export async function requireCurrentUser() {
    const currentUser = await runWithAmplifyServerContext({
        nextServerContext: { cookies },
        operation: (contextSpec) => getCurrentUser(contextSpec),
    });
    const session = await runWithAmplifyServerContext({
        nextServerContext: { cookies },
        operation: (contextSpec) => fetchAuthSession(contextSpec),
    });
    const attributes = await runWithAmplifyServerContext({
        nextServerContext: { cookies },
        operation: (contextSpec) => fetchUserAttributes(contextSpec),
    });

    return {
        currentUser,
        session,
        attributes,
    };
}

AppRunnerのデプロイでは、環境変数にHOSTNAME=0.0.0.0を指定しないとヘルスチェックに失敗する

node.jsが待ち受けるhostnameの影響で、環境変数にHOSTNAME=0.0.0.0を指定しないとAppRunnerのヘルスチェックに失敗します。

apprunner_service.add_environment_variable(
            "HOSTNAME", "0.0.0.0"
        )  # node.jsが待ち受けるhostnameの影響で、この設定がないとAppRunnerのヘルスチェックに失敗します。

参考文献