内部ループにおけるネットワーキングの概要
Aspire を使って開発する利点の一つは、クラウド ネイティブ アプリをローカル環境で開発、テスト、デバッグできることです。内部ループ ネットワーキングは、開発環境内でアプリ同士が相互に通信できるようにする Aspire の重要な要素です。本記事では、プロキシ、エンドポイント、エンドポイント構成、コンテナー ネットワークを用いて、Aspire がさまざまなネットワーキング シナリオをどのように扱うかを学びます。
内部ループにおけるネットワーキング
Section titled “内部ループにおけるネットワーキング”内部ループとは、アプリをターゲット環境にデプロイする前に、ローカル環境で開発およびテストを行うプロセスです。Aspire には、内部ループにおけるネットワーキング体験を簡素化し、向上させるためのさまざまなツールや機能が用意されています。例えば次のようなものです:
- エンドポイント/エンドポイント 構成: エンドポイントは、データベース、メッセージ キュー、API など、アプリが依存するサービスとアプリとの間の接続を表します。エンドポイントには、サービス名、ホスト ポート、スキーム、環境変数などの情報が含まれます。Aspire はリソース構成からエンドポイントを自動的に作成でき、
WithEndpointを呼び出して明示的に追加することもできます。 - プロキシ: Aspire は、アプリに追加した各サービス バインディングごとに自動的にプロキシを起動し、プロキシが待ち受けるポートを割り当てます。プロキシは、その後、アプリが待ち受けているポート(プロキシ ポートとは異なる場合があります)にリクエストを転送します。これにより、ポートの競合を回避し、一貫性があり予測可能な URL を使用してアプリやサービスにアクセスできるようになります。
- コンテナー ネットワーク: Aspire はコンテナー リソース用の専用ネットワークを作成および管理し、ローカル開発中のコンテナー間のサービス検出と通信を容易にします。
エンドポイントの仕組み
Section titled “エンドポイントの仕組み”Aspire におけるサービス バインディングは、次の 2 つの統合要素で構成されます。1 つは、アプリが必要とする外部リソース(データベース、メッセージ キュー、API など)を表す サービス、もう 1 つは、アプリとそのサービスの間の接続を確立し、必要な情報を提供する バインディング です。
Aspire は、リソース構成からサービス バインディングを自動的に作成できるほか、WithEndpoint を使用して追加のバインディングを明示的に作成することもできます。
暗黙的・明示的のいずれでバインディングが作成された場合でも、Aspire は指定されたポートで軽量なリバース プロキシを起動し、アプリからサービスへのリクエストに対するルーティングや負荷分散を処理します。このプロキシは Aspire の実装上の詳細であり、構成や管理について意識する必要はありません。
エンドポイントの動作を視覚的に理解するために、Aspire スターター テンプレートの内部ループ ネットワーキング図を確認してください:

コンテナー ネットワークの管理方法
Section titled “コンテナー ネットワークの管理方法”1 つ以上のコンテナー リソースを追加すると、Aspire はコンテナー間のサービス検出を可能にするため、専用のコンテナー ブリッジ ネットワークを作成します。このブリッジ ネットワークは、コンテナー同士が相互に通信できるようにする仮想ネットワークであり、DNS 名を使用したコンテナー間のサービス検出のための DNS サーバーも提供します。
ネットワークのライフタイムは、コンテナー リソースの設定に依存します:
- すべてのコンテナーがセッション ライフタイムの場合、ネットワークもセッション ベースとなり、AppHost プロセスの終了時にクリーンアップされます。
- いずれかのコンテナーが永続ライフタイムの場合、ネットワークは永続化され、AppHost プロセスが終了した後も稼働し続けます。Aspire は以降の実行時にこのネットワークを再利用するため、AppHost が動作していない間も、永続コンテナー同士の通信が維持されます。
コンテナーのライフタイムの詳細については、 永続コンテナーのライフタイムを参照してください。
コンテナー ネットワークの命名規則は次のとおりです:
- セッション ネットワーク:
aspire-session-network-<unique-id>-<app-host-name> - 永続ネットワーク:
aspire-persistent-network-<project-hash>-<app-host-name>
各 AppHost インスタンスは、それぞれ独自のネットワーク リソースを持ちます。異なるのはネットワークのライフタイムと名前のみで、サービス検出の仕組みはどちらの場合も同じです。
コンテナーは、自身のリソース名を使用してネットワークに登録されます。Aspire はこの名前を、コンテナー間のサービス検出に利用します。たとえば、pgadmin コンテナーは、postgres という名前のデータベース リソースに対して postgres:5432 を使って接続できます。
エンドポイントの挙動の一部は、リソースの種類によって異なります。こうした詳細は、この概要ページに重複して書くのではなく、それぞれの専用ドキュメントに分離しました。
詳細については、起動プロファイル および プロジェクト リソース を参照してください。
ポートとプロキシ
Section titled “ポートとプロキシ”サービス バインディングを定義する際、ホスト ポートは 常に サービスの前段に配置されるプロキシに割り当てられます。これにより、サービスが単一レプリカの場合でも複数レプリカの場合でも、同様に振る舞うことができます。さらに、WithReference API を使用するすべてのリソース依存関係は、環境変数から取得されるプロキシのエンドポイントに依存します。
サービスが複数レプリカで実行される場合でも、同じプロキシ パターンが適用されます。ブラウザーは 1 つの安定したホスト ポートに接続し、プロキシが利用可能なレプリカへトラフィックを振り分けます:
前述のコードにより、次のネットワーキング図が得られます:

前述の図は、次の内容を示しています:
- アプリへのエントリ ポイントとしての Web ブラウザー。
- 5066 のホスト ポート。
- Web ブラウザーとフロントエンド サービスのレプリカの間に配置され、ポート 5066 で待ち受けるフロントエンド プロキシ。
- ランダムに割り当てられたポート 65001 で待ち受ける
frontend_0フロントエンド サービス レプリカ。 - ランダムに割り当てられたポート 65002 で待ち受ける
frontend_1フロントエンド サービス レプリカ。
環境変数から待ち受けポートを読み取る JavaScript アプリでは、次のように安定したホスト ポートを公開できます:
builder.AddJavaScriptApp("frontend", "./frontend") .WithHttpEndpoint(port: 5066, env: "PORT");次の 2 つのポートが定義されています:
- 5066 のホスト ポート。
- 基になるサービスがバインドされる、ランダムに割り当てられたプロキシ ポート。

前述の図は、次の内容を示しています:
- アプリへのエントリ ポイントとしての Web ブラウザー。
- 5066 のホスト ポート。
- Web ブラウザーとフロントエンド サービスの間に配置され、ポート 5066 で待ち受けるフロントエンド プロキシ。
- ランダムに割り当てられたポート 65001 で待ち受けるフロントエンド サービス。
基になるサービスは独自のポートで待ち受け、Aspire はその割り当てられたポートを PORT 環境変数としてアプリに渡します。
ホスト ポートを省略する場合
Section titled “ホスト ポートを省略する場合”ホスト ポートを省略すると、Aspire はホスト ポートとサービス ポートの両方に対してランダムなポートを生成します。これは、ポートの競合を回避したい場合や、ホスト ポートやサービス ポートを特に意識しない場合に便利です。次のコードを例に考えてみましょう:
builder.AddJavaScriptApp("frontend", "./frontend") .WithHttpEndpoint(env: "PORT");このシナリオでは、次の図に示すように、ホスト ポートとサービス ポートの両方がランダムになります:

前述の図は、次の内容を示しています:
- アプリへのエントリ ポイントとしての Web ブラウザー。
- ランダムに割り当てられたホスト ポート 65000。
- Web ブラウザーとフロントエンド サービスの間に配置され、ポート 65000 で待ち受けるフロントエンド プロキシ。
- ランダムに割り当てられたポート 65001 で待ち受けるフロントエンド サービス。
コンテナー ポート
Section titled “コンテナー ポート”コンテナー リソースを追加すると、Aspire は自動的にランダムなポートをコンテナーに割り当てます。コンテナー ポートを指定するには、目的のポートを使用するようにコンテナー リソースを構成します:
builder.AddContainer("frontend", "mcr.microsoft.com/dotnet/samples", "aspnetapp") .WithHttpEndpoint(port: 8000, targetPort: 8080);前述のコードでは、次のことが行われています:
mcr.microsoft.com/dotnet/samples:aspnetappイメージから、frontendという名前のコンテナー リソースを作成します。- ホストをポート 8000 にバインドし、コンテナーのポート 8080 にマッピングしつつ、
httpエンドポイントを公開します。
次の図を参照してください:

エンドポイント拡張メソッド
Section titled “エンドポイント拡張メソッド”IResourceWithEndpoints インターフェイスを実装する任意のリソースは、WithEndpoint 拡張メソッドを使用できます。この拡張メソッドには複数のオーバーロードがあり、スキーム、コンテナー ポート、ホスト ポート、環境変数名、そしてエンドポイントをプロキシ経由にするかどうかを指定できます。
また、エンドポイントを構成するためのデリゲートを指定できるオーバーロードもあります。これは、環境やその他の要因に応じてエンドポイントを構成する必要がある場合に便利です。次のコードを例に考えてみましょう:
builder.AddContainer("apiService", "nginx") .WithEndpoint( endpointName: "admin", callback: static endpoint => { endpoint.Port = 17003; endpoint.UriScheme = "http"; endpoint.Transport = "http"; });前述のコードでは、エンドポイントを構成するためのコールバック デリゲートが提供されています。このエンドポイントは admin という名前で、http スキームおよびトランスポートを使用し、ホスト ポート 17003 に構成されています。コンシューマーは http://_admin.apiservice のような URI で、このエンドポイントを名前で参照できます。_ プレフィックスは、admin セグメントが apiservice サービスに属するエンドポイント名であることを示すための規約です。詳細については、サービス検出を参照してください。
追加の考慮事項
Section titled “追加の考慮事項”WithEndpoint 拡張メソッドを呼び出す際、callback オーバーロードでは生の EndpointAnnotation が公開され、これによりエンドポイントのさまざまな側面をカスタマイズできます。
AllocatedEndpoint プロパティを使用すると、サービスのエンドポイントを取得または設定できます。IsExternal と IsProxied プロパティは、エンドポイントの管理方法や公開方法を決定します。IsExternal は公開アクセス可能かどうかを決定し、IsProxied は DCP による管理を有効にして、内部ポートの違いやレプリケーションを可能にします。
Name プロパティはサービスを識別し、Port および TargetPort プロパティは、それぞれ希望するポートと実際に待ち受けるポートを指定します。
ネットワーク通信に関しては、Protocol プロパティが TCP および UDP をサポートしており、将来的にはさらに追加される可能性があります。また、Transport プロパティはトランスポート プロトコル(HTTP、HTTP2、HTTP3)を示します。最後に、サービスが URI でアドレス指定可能な場合、UriScheme プロパティがサービス URI を構築するための URI スキームを提供します。
詳細については、EndpointAnnotation のプロパティ一覧を参照してください。
プロジェクト リソース固有のエンドポイント フィルタリングについては、プロジェクト リソース を参照してください。