フロントエンド サービスとバックエンド サービスを組み合わせたフル スタック アプリケーションは、最新の Web 開発で一般的なパターンです。 Azure Developer CLI (azd) では、フロントエンドとバックエンドが個別のサービスとしてホストされるフル スタック アプリケーションのデプロイがサポートされています。 この記事では、 azd を使用してフル スタック アプリケーションをデプロイする方法について説明し、効果的なデプロイのための戦略と利点について説明します。
フル スタックデプロイとは
azdを使用したフル スタックデプロイは、通常、次で構成されます。
- フロントエンド サービス: ユーザー向けの Web アプリケーション。多くの場合、React、Angular、Vue、Blazor などのフレームワークで構築されます。 フロントエンドは、静的サイトまたはコンテナー化されたアプリケーションとしてホストされる場合があります。
- バックエンド サービス: ビジネス ロジック、データ アクセス、統合を処理する API またはサービス レイヤー。 バックエンドは通常、コンテナーまたはサーバーレス関数としてホストされます。
- 共有リソース: データベース、ストレージ アカウント、キー コンテナー、および両方のサービスが使用する可能性があるその他の Azure リソース。
azdを使用すると、1 つのazure.yaml ファイルに両方のサービスを定義し、コードとしてのインフラストラクチャ (Bicep または Terraform) を使用してそれらを一緒にプロビジョニングできます。
Azure Developer CLI のライフサイクル
Azure Developer CLI は、個別のライフサイクル イベントを含む構造化されたワークフローに従います。
- パッケージ: アプリケーションのソース コードをビルドし、デプロイ用に成果物を準備します。
- プロビジョニング: Bicep または Terraform を使用して Azure インフラストラクチャ リソースを作成または更新します。
- デプロイ: プロビジョニングされたインフラストラクチャにパッケージ化されたアプリケーション コードをデプロイします。
azd up コマンドは、3 つのフェーズすべてを順番に実行します。
azd package、azd provision、azd deployを使用して各フェーズを個別に実行して、より詳細な制御を行うこともできます。 このライフサイクルを理解することは、サービス間の依存関係を管理するために不可欠です。特に、タイミングと順序が重要なフル スタックデプロイでは重要です。
azdライフサイクルとワークフローのカスタマイズの詳細については、「azd up ワークフローを調べる」を参照してください。
インフラストラクチャの設計に関する考慮事項
azdを使用してフル スタック アプリケーションを設計する場合は、フロントエンドとバックエンドに適した Azure ホスティング サービスを選択します。
| サービスの種類 | ホスティング オプション | 利用シーン |
|---|---|---|
| フロントエンド | Azure Static Web Apps、 Azure App Service、 Azure Container Apps | 静的サイト、SPA、サーバーでレンダリングされたアプリ |
| バックエンド | Azure Container Apps、 Azure App Service、 Azure Functions、 Azure Kubernetes Service | API、マイクロサービス、サーバーレス関数 |
Azure でのアプリケーションのホストの詳細について説明します。
フロントエンド アプリケーションとバックエンド アプリケーションの相互依存関係を理解する
フルスタックデプロイでは、多くの場合、完全に構成する前に各サービスが他方に関する情報を必要とする循環依存関係の課題が発生します。 これらの相互依存関係を理解することは、効果的なデプロイ ワークフローを設計するのに役立ちます。
フロントエンドにはバックエンド URL が必要です。通常、フロントエンド アプリケーションは、ビルド時または実行時にバックエンド API エンドポイント URL を認識する必要があります。 ただし、バックエンド サービスは、Azure にデプロイされるまで URL を持ちません。
バックエンドにはフロントエンド URL が必要です。バックエンド サービスでは、CORS ポリシーを構成するためにフロントエンド URL が必要な場合がありますが、展開されるまでフロントエンドには URL がありません。
共有リソースの依存関係: どちらのサービスも、データベース、キー コンテナー、ストレージ アカウントなどの共有リソースに依存する場合があります。 これらのリソースを使用するようにいずれかのサービスを構成する前に、これらのリソースをプロビジョニングする必要があります。
環境固有の構成: 異なる環境 (開発、ステージング、運用) には異なるエンドポイント URL と構成が必要ですが、これらの値はプロビジョニングが完了するまで認識されません。
構成戦略を理解する
Azure Developer CLI は、次の 2 つの方法を使用して、これらの相互依存関係を処理します。
- デプロイ時の構成: プロビジョニングとデプロイ中に依存関係を解決する
- ランタイム構成: 依存関係の構成をアプリケーションの実行時に延期する
これらのアプローチは、アプリケーションのビルド時に行う設計上の決定を表します。 1 つの戦略のみを使用するか、アーキテクチャと要件に応じて両方を組み合わせることができます。
デプロイ時の構成
デプロイ時の構成とは、サービス接続と構成が決定され、 azd provision フェーズと azd deploy フェーズ中にロックされることを意味します。 この方法を使用すると、実行を開始する前に、特定のエンドポイント URL、接続文字列、およびその他の依存関係情報を含むサービスを構成できます。 この構成は、環境変数として、またはデプロイと共にパッケージ化された構成ファイル内で、デプロイされたサービスの環境の一部になります。
インフラストラクチャ優先プロビジョニング: azd up または azd provisionを実行すると、最初にインフラストラクチャが作成されます。 この手順では、デプロイを開始する前に必要な URL と接続文字列が生成され、依存サービスに必要な情報が確実に含まれるようにします。
出力変数: Bicep と Terraform は、プロビジョニング後に URL や接続文字列などの値を出力できます。 これらの出力はデプロイ フェーズ中に環境変数として使用できるようになるため、開始する前に適切なエンドポイントを使用してサービスを構成できます。
順次デプロイ: 複雑なシナリオでは、特定の順序でサービスをデプロイすることが必要になる場合があります。
azd
hook を使用して展開シーケンスを制御し、依存サービスを展開する前に前提条件となるサービスが確実に実行されるようにします。
Container upsert パターン: Azure Verified Modules (AVM) は、container-app-upsertの 2 フェーズ ワークフローとシームレスに連携するazdなどのコンテナー アプリ パターンを提供します。 プロビジョニング中に、インフラストラクチャと初期コンテナーが作成されます。 デプロイ時に、 azd は、データベース接続文字列やサービス URL など、プロビジョニング中に生成された値を含む更新された環境変数でコンテナー イメージをアップサートします。 このパターンでは、最初にインフラストラクチャを存在させ、次に必要なすべての依存関係情報を使用してコンテナー構成を更新することで、鶏と卵の問題を解決します。
コンテナー API バックエンドを使用した React フロントエンドのワークフロー例:
-
azd upを実行します。パッケージ、プロビジョニング、デプロイの各フェーズを順番に実行します。 - プロビジョニング中、Bicep は AVM
container-app-upsertモジュールを使用して Azure Container Apps インフラストラクチャを作成し、バックエンド API URL を出力します。 - デプロイ時に、
azdは、フロントエンドの API URL を含む正しい環境変数を使用して両方のコンテナーを自動的にアップサートします。 - どちらのサービスも、正しい構成で開始されます。
azd upまたはazd deployの今後の実行により、新しい構成値でコンテナーが更新されます。
ランタイム構成
ランタイム構成を使用すると、デプロイ時ではなく、アプリケーションの実行時にアプリケーションが構成を読み込むことができます。 この方法では、アプリケーションを再デプロイすることなく、サービス エンドポイント、接続文字列、ポリシーを柔軟に更新できます。
構成ソース: アプリケーションは、次の 2 つの主要なソースからランタイム構成を読み込むことができます。
ローカル構成ファイル:
config.jsonなどの構成ファイルをアプリケーションと共にデプロイします。 アプリケーションは起動時にこのファイルを読み込み、現在のエンドポイント URL、認証設定、およびその他の構成値を取得します。 このアプローチは、アプリケーションがブラウザーで起動したときに構成をフェッチできる React、Angular、Vue、Blazor WebAssembly などのクライアント側フレームワークに適しています。クラウド構成サービス: Azure App Configuration または同様のサービスを使用して、すべての環境で構成を一元的に管理します。 アプリケーションは、起動時またはオンデマンドで構成サービスにクエリを実行して、現在の値を取得します。 このアプローチは、複数のサービスで調整された構成の更新が必要なマイクロサービス アーキテクチャに役立ちます。
利点: どちらの方法でも、構成の変更は再デプロイなしですぐに使用できるようになります。 デプロイ パイプラインを使用して構成ファイルを更新するか、Azure portal を使用して Azure App Configuration の値を変更します。 アプリケーションは、構成を再起動または更新すると、新しい値を選択します。 このパターンは、次の場合に特に役立ちます。
- バックエンド API URL、認証エンドポイント、マイクロサービスの場所を検出する必要があるフロントエンド アプリケーション
- フロントエンド URL の変更に応じて CORS ポリシーを更新する必要があるバックエンド サービス
- 開発環境、ステージング環境、運用環境間で異なる構成を必要とするサービス
バックエンド API を検出する React フロントエンドのワークフロー例:
-
azd upを実行してインフラストラクチャをプロビジョニングし、両方のサービスをデプロイします。 - デプロイ後フックは、バックエンド URL を含む
config.jsonファイルを生成し、フロントエンドのストレージの場所にアップロードします。 - React アプリは、起動時に
config.jsonをフェッチして API エンドポイントを検出します。 - エンドポイントを後で更新するには、フロントエンドを再デプロイせずに
config.jsonを変更します。
この方法は、ビルド時にすべてのコンテンツが事前にレンダリングされる静的に生成されたサイトでは機能しません。
デプロイ ワークフローを計画する
フルスタックデプロイを設計するときは、次の要因を考慮してください。
- 依存関係を特定する: 他のサービスからの情報が必要なサービスをマップします。 一方向の依存関係 (データベースに応じた API など) の場合、プロビジョニング プラットフォーム (Bicep または Terraform) によって順序が自動的に処理されます。 循環依存関係 (起動時に互いの URL を必要とするフロントエンド サービスやバックエンド サービスなど) の場合は、デプロイ時またはランタイム構成戦略を使用して調整を設計する必要があります。
- デプロイ前にプロビジョニングする: アプリケーション コードをデプロイする前にすべてのインフラストラクチャが存在することを確認します。
- 環境変数を使用する: azd 環境変数を使用して、インフラストラクチャレイヤーとアプリケーションレイヤーの間で構成を渡します。
- 複数の環境向けの設計: 開発環境、ステージング環境、運用環境間での構成の違いを計画します。
- デプロイ順序を検討する: シナリオによっては、特定の順序でサービスをデプロイする必要がある場合があります。
azd up コマンドは、プロビジョニングを自動的に実行し、その後に 1 つのワークフローでデプロイすることで、ほとんどのデプロイ シナリオを処理します。 標準の単一アプリケーションの場合、このアプローチは適切に機能し、最小限の構成が必要です。
循環依存関係を持つ完全なスタックなど、より複雑なデプロイの場合:
サービスの順序を構成する:
azure.yamlファイルで、デプロイする順序でサービスを定義します。azdは既定でサービスを並列にデプロイしますが、フックを使用して、必要に応じて順次デプロイを適用できます。ワークフロー ステップをカスタマイズする:
azd upファイルでカスタムworkflowsプロパティを定義して、既定のazure.yamlワークフローをオーバーライドします。 たとえば、アプリケーションのソース コードをビルドする前に、プロビジョニングを実行するように既定の動作を変更できます。name: todo-nodejs-mongo metadata: template: todo-nodejs-mongo@0.0.1-beta workflows: up: steps: - azd: provision - azd: package - azd: deployこのパターンは、プロビジョニングが完了した後にのみ使用可能な構成値がビルド プロセスに必要な場合に便利です。
個別のプロビジョニングとデプロイ:
azd upを使用する代わりに、azd provisionとazd deployを個別のコマンドとして実行します。 この分離は、アプリケーション コードをデプロイする前にインフラストラクチャの構成を確認する必要がある場合や、デプロイの問題のトラブルシューティングを行う場合に便利です。 インフラストラクチャを 1 回プロビジョニングした後、再プロビジョニングせずにアプリケーション コードを複数回デプロイおよび再デプロイできます。フックを使用してカスタマイズする: ファイルに事前フックとポスト
azure.yamlを追加して、プロビジョニングフェーズとデプロイ フェーズの間でカスタム ロジックを実行します。 フックを使用して、構成ファイルの設定、環境の状態の検証、または複雑なデプロイ シーケンスの調整を行います。
ベスト プラクティス
azdを使用してフル スタック アプリケーションを構築する場合は、次のベスト プラクティスに従ってください。
- 依存関係を早期にマップする: 設計フェーズ中に他のサービスからの情報が必要なサービスを特定します。 Bicep または Terraform が自動的に処理する一方向の依存関係と、デプロイ時またはランタイム構成戦略を必要とする循環依存関係を区別します。
- 適切な構成戦略を選択する: デプロイ時にサービスが構成をロックする必要がある場合は、デプロイ時の構成を使用します。 再デプロイせずに構成を柔軟に更新する必要がある場合は、ランタイム構成を使用します。 必要に応じて、両方の戦略を組み合わせます。
-
Azure 検証済みモジュール (AVM) の使用: コンテナー アプリのなどの
container-app-upsertBicep モジュールを活用します。 これらのパターンは、azdの 2 フェーズ ワークフローとシームレスに連携して、循環依存関係を解決します。 -
必要に応じてワークフローをカスタマイズする: 単純なデプロイの場合は、既定の設定で
azd upを使用します。 循環依存関係がある複雑なシナリオでは、workflowsファイル内のazure.yamlプロパティをカスタマイズして、パッケージ、プロビジョニング、デプロイの手順の順序を制御します。 - ランタイム構成を活用する: 環境全体の柔軟性を最大限に高めるために、Azure App Configuration またはローカル構成ファイルを使用して、再デプロイせずに更新できるサービス エンドポイントと設定を管理します。
- 複数の環境でテストする: サービスの URL と構成が異なる開発、ステージング、運用環境で構成戦略が正しく機能することを確認します。