Next.jsアプリケーションをAWS App Runnerにデプロイする実践ガイド

目次

はじめに

皆さん、Next.jsアプリケーションをデプロイするとき、どんなサービス上にデプロイしてますでしょうか?

Vercel? Amplify? はたまたCloud Run? 様々な候補があると思いますがこの記事では、AWS CDK(Cloud Development Kit)を使って、Next.jsアプリケーションをApp Runnerにデプロイし、Route53を使ったカスタムドメイン設定を自動化するまでの手法をご紹介します。

特に、AWS Lambda Custom Resourceを活用した証明書検証やDNSレコード管理など、CDKによる完全なる自動化を目標にしました。

前提条件

こちらのリポジトリから今回使用するソースコードをご確認いただけます。

  • AWSアカウントがあること
  • AWS CLIがインストールされ、適切に設定されていること
  • Node.js v22.x以上
  • pnpm v10.x以上
  • AWS CDK v2
  • 有効なルートドメインがRoute53に登録されていること

アーキテクチャ

AWS App Runnerは、コンテナ化されたアプリケーションをインフラ管理なしでデプロイできるフルマネージドサービスで、Next.jsアプリケーションを高可用性、スケーラビリティ、運用の簡素化などと様々な面で期待できるサービスとなっております。

今回の構成では、以下のAWSサービスを組み合わせて使用します。

  • AWS App Runner: Next.jsアプリケーションをホスティングするサービスです。スケーリングやデプロイを自動的に処理してくれるので、インフラの心配をする必要がありません。
  • Amazon Route53: DNSレコードを管理し、カスタムドメイン(例:app.example.com)をApp Runnerサービスに向けるためのサービスです。
  • AWS Certificate Manager (ACM): HTTPSで安全に通信するために必要なSSL/TLS証明書を発行・管理します。
  • AWS Lambda: カスタムリソースとして使い、ドメイン検証を自動化します。普通なら手動でやる必要がある作業を今回はLambdaを使って自動化していきます。
  • AWS IAM: 各サービスに適切な権限を付与して、セキュリティを確保します。

今回のご紹介する構成には、以下のような特徴があります:

  1. IaC(Infrastructure as Code)アプローチ: AWSリソースをコードとして定義するので、環境の再現性が高まりヒューマンエラーを起こしにくくできます。
  2. モジュール化された設計: 再利用可能なCDKコンストラクトを作成することで、似たようなインフラを簡単に構築できるようになります。
  3. 自動化されたDNS検証: これが本当にすごいところで、手動操作なしでSSL証明書を検証できます。AWSコンソールでポチポチする必要がなくなリます!
  4. クリーンな依存関係管理: リソース間の依存関係を明示的に定義することで、デプロイの安定性が向上します。

プロジェクト構造

プロジェクトのディレクトリ構造は以下のような構成になっています。

実装の詳細

インフラストラクチャスタック

まずは全体のインフラを定義するCDKスタックを見てみましょう。このスタックが、App Runnerサービスのデプロイとカスタムドメイン設定の中心となります。

このコードがやっていることを、分かりやすく説明します。

  1. スタックのプロパティ: InfraStackPropsインターフェースで、環境名やアプリケーション名、ドメイン設定などのパラメータを定義しています。これらの値は、あなたが.envファイルで設定した値が入ります。
  2. App Runnerのデプロイ: deployAppRunnerServiceメソッドでは、Next.jsアプリケーションを動かすためのApp Runnerサービスを構成しています。CPUやメモリのサイズ、環境変数、ヘルスチェックの設定なども行っていますよ。
  3. カスタムドメイン設定: configureCustomDomainメソッドでは、ホストゾーン名とサブドメイン名が指定されている場合に、Route53の設定を行います。この部分が、あなたのカスタムドメイン(例:app.example.com)をApp Runnerサービスに紐づける役割を担っています。
  4. 出力の定義: createStackOutputsメソッドでは、WebアプリケーションのURLを出力として定義しています。これにより、デプロイ完了後にアクセス先のURLが表示されますし、他のスタックやCI/CDパイプラインからもこの値を参照できるようになります。

Route53設定コンストラクト

次に、Route53の設定を担当するコンストラクトを見てみましょう。このコンポーネントが、HTTPSを使ったカスタムドメイン設定の中核となります。

このRoute53Configコンストラクトは、カスタムドメイン設定の中核となる複雑なロジックをカプセル化しています。主な機能と実装上のポイントを見ていきます:

  1. App Runner用のホストゾーンマッピング:リージョンごとのApp RunnerサービスのホストゾーンIDを定義しています。これはALIASレコードを設定する際に必要となります。
  2. 証明書自動検証:AWS Certificate Manager(ACM)で発行したSSL/TLS証明書の検証プロセスを自動化するためのカスタムリソースを実装しています。
  3. カスタムドメイン関連付け:App RunnerサービスとカスタムドメインとのAssociation(関連付け)を処理するLambda関数を作成しています。
  4. DNSレコード設定:AレコードまたはCNAMEレコードを自動的に設定し、カスタムドメインからApp Runnerサービスへのルーティングを確立します。
  5. リソース間の依存関係管理:各リソースの作成順序とデプロイ依存関係を明示的に定義しています。

特に、createValidationHandlercreateCustomDomainFunctionメソッドは、Lambda関数を使ったカスタムリソースプロバイダーの作成方法を示しており、CDKの高度な使い方を実装しています。これにより、CloudFormationだけでは直接サポートされていない操作(証明書の検証やApp Runnerのカスタムドメイン設定など)を自動化しています。

Lambdaによる証明書検証の自動化

Route53Configコンストラクトの中核機能の一つ、SSL/TLS証明書の検証を自動化するLambda関数を見ていきましょう。この関数によって証明書のDNS検証レコードの作成・更新が全部自動で設定が可能になってます。

このLambda関数は、CloudFormationのカスタムリソースのライフサイクルイベント(Create、Update、Delete)に応じて証明書の検証レコードをRoute53に自動的に作成・更新・削除します。一見複雑に見えるかもしれませんが、主に以下のことをやっています:

  1. ACMからの検証情報取得: AWS Certificate Manager(ACM)から、証明書に関連する検証情報を取得します。これには「どんなDNSレコードを作れば証明書が検証されるか」という情報が含まれています。
  2. Route53でのレコード操作: 取得した検証情報を元に、Route53にCNAMEレコードを作成・更新・削除します。これにより、SSLの検証が完全に自動化されます。
  3. エラー処理と再試行: ネットワークエラーやタイミングの問題に備えて、リトライロジックも実装しています。証明書の情報がすぐに利用できない場合でも、数回試行してくれます。

特に注目してほしいのは retryOperation 関数です。AWS APIの呼び出しはたまに一時的なエラーが発生することがあるので、こういった再試行の仕組みがあると信頼性が大幅に向上します。しかも、単純な再試行ではなく「指数バックオフ」という手法を使っているんですよ。これは待機時間を徐々に長くしていく方法で、AWSのベストプラクティスに沿ったアプローチです。

カスタムドメイン関連付けのLambda関数

お次は、App Runnerサービスとカスタムドメインを関連付けるLambda関数を見ていきましょう。このLambda関数も、CloudFormationでは直接サポートされていない操作を自動化するためのカスタムリソースとして機能します。

このLambda関数も、とても重要な役割を担っています。具体的には以下のことをやっています:

  1. カスタムドメインの関連付け: App Runnerサービスに対して、カスタムドメイン(例:app.example.com)を関連付けます。これにより、指定のドメインでアプリにアクセスできるようになります。
  2. 状態の監視: 関連付けは非同期で行われるため、状態を監視する機能も実装されています。waitForCustomDomainStatusメソッドがその役割を担います。
  3. 柔軟な更新処理: ドメイン名が変更された場合には、古いドメインの関連付けを解除してから、新しいドメインを関連付けるという処理もサポートしています。
  4. CloudFormationとの連携: この関数はカスタムリソースとして動作するため、CloudFormationのライフサイクルイベント(Create、Update、Delete)と連携しています。

この関数のおかげで、App Runnerのカスタムドメイン設定がCloudFormationのスタックライフサイクルに組み込まれ、完全に自動化できるようになってます。

デプロイ方法

さて、ここまで説明してきたコードを使って、実際にNext.jsアプリをデプロイしてみましょう!

AWS CDKからApp Runnerへのデプロイ手順をご紹介します。

環境変数の設定

まずは、デプロイに必要な環境変数を設定していきましょう。プロジェクトのルートディレクトリに .env ファイルを作成して、以下のように設定してください。これらの変数がインフラ構築を制御します。

デプロイ手順

準備ができたら、以下のコマンドを順番に実行してインフラをデプロイしていきましょう。

デプロイが無事完了すると、ターミナルに以下のような出力が表示されます。これらのURLを開いてアプリケーションにアクセスできるようになっているのが確認できたらOKです。

今回私はcreate-next-appの初期のままデプロイしたのでドメインにアクセスすると以下のページが開けました。

まとめ

この記事では、AWS App RunnerでNext.jsアプリケーションをデプロイし、カスタムドメインを設定する方法について詳しく解説しました。

  1. AWS CDKによる自動化: インフラをコードとして管理し、複雑な設定を自動化することで、デプロイの再現性と信頼性を高めました。
  2. カスタムドメイン設定の自動化: Route53Configコンストラクトを使って、SSL/TLS証明書の発行・検証からDNSレコードの設定まで、すべてを自動化しました。
  3. Lambda関数による拡張: CloudFormationでは直接サポートされていない操作を、カスタムリソースとLambda関数を組み合わせることで実現しました。
  4. セキュリティとパフォーマンスの最適化: 最小権限の原則に基づいたIAM設定や、適切なリソースサイジングにより、安全かつコスト効率の良いデプロイを実現しました。

この実装アプローチにより、開発者はインフラの複雑さを気にすることなく、アプリケーション開発に集中できるようになります。また、環境の再構築も簡単に行えるため、開発からステージング、本番環境まで一貫したデプロイパイプラインを構築できます。

AWS App RunnerとCDKを組み合わせることで、コンテナ技術の複雑さを抽象化しつつ、カスタムドメインやSSL/TLS証明書などの本番環境に必要な要素を簡単に導入できるようになったかと思います。

 

他にも技術ブログをあげているのでそちらもよろしければ見ていってださい。

私のブログ記事一覧

 

また、株式会社ギークフィードでは開発エンジニアなどの職種で一緒に働く仲間を募集しています。

弊社に興味を持っていただいたり、会社のことをカジュアルに聞いてみたいという場合でも、ご気軽にフォームからお問い合わせください。その場合はコメント欄に、カジュアルにお話したいです、と記載ください!

採用情報はコチラ

この記事が気に入ったら
いいね ! しよう

Twitter で

【採用情報】一緒に働く仲間を募集しています

採用情報
ページトップへ