AppHost とは?
Aspire の AppHost は、アプリケーションのサービスやそれらの関係性を コードファーストで宣言するための場所です。分散した設定ファイルを管理する代わりに、アーキテクチャをコードで記述します。その後のローカル オーケストレーションは Aspire が担ってくれるため、機能開発に集中できます。
アーキテクチャの定義
Section titled “アーキテクチャの定義”フロントエンドが API と通信し、API がデータベースと通信する、シンプルな 3 層アーキテクチャを考えてみましょう:
architecture-beta service db(logos:postgresql)[PostgreSQL] service api(logos:dotnet)[API service] service frontend(logos:react)[React front end] api:R --> L:db frontend:R --> L:api
このアーキテクチャは、次のように AppHost で表現できます:
var builder = DistributedApplication.CreateBuilder(args);
// Add database resourcevar postgres = builder.AddPostgres("db") .AddDatabase("appdata") .WithDataVolume();
// Add API service and reference the databasevar api = builder.AddProject<Projects.Api>("api") .WithReference(postgres) .WaitFor(postgres);
// Add frontend service and reference the APIbuilder.AddViteApp("frontend", "../frontend") .WithHttpEndpoint(env: "PORT") .WithReference(api);
builder.Build().Run();Aspire は、使用する言語やフレームワークに関係なく、サービス、リソース、そしてそれらの接続関係という一貫したモデルを提供します。
AppHost コードの分解
Section titled “AppHost コードの分解”ここでは、典型的な AppHost の主要な部分を取り上げ、各ステップが何をしているのかを説明します。
var builder = DistributedApplication.CreateBuilder(args);
14 collapsed lines
// Add database resourcevar postgres = builder.AddPostgres("db") .AddDatabase("appdata") .WithDataVolume();
// Add API service and reference the databasevar api = builder.AddProject<Projects.Api>("api") .WithReference(postgres) .WaitFor(postgres);
// Add frontend service and reference the APIbuilder.AddViteApp("frontend", "../frontend") .WithHttpEndpoint(env: "PORT") .WithReference(api);
builder.Build().Run();展開されている行では、次の処理を行っています:
DistributedApplication.CreateBuilder(args)を使用して、分散アプリケーション ビルダーを作成します。Build()を呼び出して、構成を実行可能な AppHost として具体化します。Run()を呼び出してオーケストレーションを開始し、サービスは依存関係の順序に従って起動されます。
AppHost は分散アプリケーションの設計図であり、残りの処理は Aspire が管理します。
PostgreSQL リソースの追加
Section titled “PostgreSQL リソースの追加”ビルダーの準備ができたら、リソースやサービスを定義します。次のスニペットは、PostgreSQL サーバーとデータベースを追加する方法を示しています:
var builder = DistributedApplication.CreateBuilder(args);
// Add database resourcevar postgres = builder.AddPostgres("db") .AddDatabase("appdata") .WithDataVolume();
11 collapsed lines
// Add API service and reference the databasevar api = builder.AddProject<Projects.Api>("api") .WithReference(postgres) .WaitFor(postgres);
// Add frontend service and reference the APIbuilder.AddViteApp("frontend", "../frontend") .WithHttpEndpoint(env: "PORT") .WithReference(api);
builder.Build().Run();仕組みの説明:
AddPostgres("db")は、dbという名前の PostgreSQL コンテナーを登録します。- これは
IResourceBuilder<PostgresServerResource>を返すため、Fluent スタイルで設定を連結できます。
- これは
.AddDatabase("appdata")は、そのサーバー上にappdataという名前のデータベースを作成します。.WithDataVolume()は、コンテナーの再起動後もデータが保持されるように、ボリュームをプロビジョニングします。
詳しくは公式の PostgreSQL integrationをご覧ください。
API リソースの追加と依存関係の宣言
Section titled “API リソースの追加と依存関係の宣言”次に、API サービスを登録し、PostgreSQL リソースに接続します:
6 collapsed lines
var builder = DistributedApplication.CreateBuilder(args);
// Add database resourcevar postgres = builder.AddPostgres("db") .AddDatabase("appdata") .WithDataVolume();
// Add API service and reference the databasevar api = builder.AddProject<Projects.Api>("api") .WithReference(postgres) .WaitFor(postgres);
6 collapsed lines
// Add frontend service and reference the APIbuilder.AddViteApp("frontend", "../frontend") .WithHttpEndpoint(env: "PORT") .WithReference(api);
builder.Build().Run();これで行われること:
AddProject<Projects.Api>("api")は、API プロジェクトをapiという名前のサービスとして登録します。WithReference(postgres)は、接続情報(ホスト、ポート、資格情報、接続文字列)を API の構成に注入します。WaitFor(postgres)は、PostgreSQL が正常状態(healthy)になるまで API の起動を遅らせ、起動タイミングに依存した脆さを避けます。
これで api サービスが定義できたので、次はフロントエンドを接続できます。
フロントエンド リソースの追加
Section titled “フロントエンド リソースの追加”フロントエンド プロジェクトを登録し、API への依存関係を宣言すると、AppHost が API のアドレスを自動的に提供します。
11 collapsed lines
var builder = DistributedApplication.CreateBuilder(args);
// Add database resourcevar postgres = builder.AddPostgres("db") .AddDatabase("appdata") .WithDataVolume();
// Add API service and reference the databasevar api = builder.AddProject<Projects.Api>("api") .WithReference(postgres) .WaitFor(postgres);
// Add frontend service and reference the APIbuilder.AddViteApp("frontend", "../frontend") .WithHttpEndpoint(env: "PORT") .WithReference(api);
builder.Build().Run();ポイント:
.AddViteApp("front end", "../frontend")は、(Vite ベースの)フロントエンド プロジェクトをfront endという名前のサービスとして登録します。.WithHttpEndpoint(env: "PORT", targetPort: 3000)は、アプリケーションをポート3000で公開します。PORT環境変数で上書きすることも可能です。.WithReference(api)は、API のベース アドレスをフロントエンドの構成に注入します
要するに、バックエンド(DB → API)を先に定義し、その後 UI から API を参照するという流れです。 AppHost は、依存関係のグラフ、接続の流れ、起動順序をまとめて管理します。
構成とネットワーク
Section titled “構成とネットワーク”これらの依存関係や接続は、Aspire によって自動的に管理されます。AppHost は、接続文字列やエンドポイントといった構成値を生成し、必要に応じて各サービスへ注入します。 AppHost でリソースを追加する際には、 db, api, front end のように名前を付けますが、Aspire はこれらの名前を DNS 解決に使用するため、サービス同士は予測可能なアドレスで通信できます。また、利用側のサービスは、これらの名前を基に構成情報の注入を受け取ります。
architecture-beta service db(logos:postgresql)[pg] service epr(iconoir:server-connection)[Endpoint Reference] service api(logos:dotnet)[api] service ctr(iconoir:server-connection)[Connection String Reference] service frontend(logos:react)[front end] db:L <-- R:ctr ctr:L <-- R:api api:L <-- R:epr epr:L <-- R:frontend
How these resources communicate
pg、接続文字列(ホスト、ポート、データベース、ユーザー、パスワード)をまとめた、Aspire が理解できる強く型付けされたConnectionStringReference(host, port, database, user, password) を公開します。apiはその参照への依存関係を宣言し、Aspire はローカル実行時・デプロイ時の両方において、シークレット、パラメーター、接続文字列を含む設定値を注入する独自の構成フローを通じて、接続文字列を設定に注入します。apiは、HTTP エンドポイントが割り当てられた後に、自身のベース URL としてEndpointReferenceを公開します。front endはそのエンドポイントに依存し、Aspire が API のベース URL を注入するため、アドレスをハードコードする必要がありません。
AppHost の仕組み
Section titled “AppHost の仕組み”AppHost を実行すると、Aspire は次のような中核的な役割を担います:
- サービス検出: AppHost に宣言されたサービスやリソースを検出します。
- 依存関係の解決: 宣言された依存関係に基づき、正しい順序でサービスを起動します。
- 構成情報の注入: 接続文字列、エンドポイント、その他の構成値を自動的に注入します。
- 状態監視: サービスの状態を監視し、必要に応じて再起動します。
Aspire のオーケストレーションや リソースモデルについて、さらに詳しくご覧ください。
AppHost の構成
Section titled “AppHost の構成”テンプレートの AppHost は、次のような構成になっています:
ディレクトリAspireApp.AppHost
- apphost.cs 開発時オーケストレーター
- apphost.run.json
ディレクトリAspireApp.AppHost
ディレクトリProperties
- launchSettings.json
- appsettings.Development.json
- appsettings.json
- AspireApp.AppHost.csproj
- AppHost.cs 開発時オーケストレーター
AppHost のライフサイクル イベント
Section titled “AppHost のライフサイクル イベント”AppHost では、起動時やリソース割り当ての過程でカスタム ロジックを実行するために、ライフサイクル イベントにフックできます。
BeforeStartEvent: AppHost がサービスの起動を開始する前に発生します。AfterEndpointsAllocatedEvent: サービスのエンドポイントが割り当てられた後に発生します。AfterResourcesCreatedEvent: すべてのリソースが作成された後に発生します。
より細かなライフサイクル制御については、 既知のライフサイクル イベントをご覧ください。
ベスト プラクティス
Section titled “ベスト プラクティス”- まずは AppHost をシンプルに保ち、必要に応じて段階的に複雑さを追加しましょう。
.WithReference(...)を使って明示的に依存関係を定義し、接続関係を分かりやすくします。- 開発・テスト・本番で構成を分けて管理しましょう。
- デバッグやログを容易にするため、リソースには分かりやすく説明的な名前を付けましょう。