Docker Compose から Aspire への移行
本ガイドは、Docker Compose から Aspire へのアプリケーション移行方法を理解し、主要な概念的違いを強調し、一般的な移行シナリオに対する正確で実践的な例を提供します。
違いを理解する
Section titled “違いを理解する”Docker Compose と Aspire は一見似ているかもしれませんが、異なる目的に対応し、異なる抽象化レベルで動作します。
Docker Compose 対 Aspire
Section titled “Docker Compose 対 Aspire”| Docker Compose | Aspire | |
|---|---|---|
| 主な目的 | コンテナオーケストレーション | 開発時のオーケストレーションとアプリケーション構成 |
| スコープ | コンテナ中心 | マルチリソース (.NET プロジェクト、クラウドリソース) |
| 構成 | YAML ベース | C# ベース、強く型付けされた |
| ターゲット環境 | あらゆる Docker ランタイム | 開発およびクラウドデプロイメント |
| サービス検知 | DNS ベースのコンテナ検知 | 環境変数による組み込みサービス検知 |
| 開発体験 | 手動でのコンテナ管理 | 統合ツーリング、ダッシュボード、テレメトリー |
主要な概念的シフト
Section titled “主要な概念的シフト”Docker Compose から Aspire に移行する際は、以下の概念的違いを検討してください:
- YAML から C# へ — 構成が宣言的 YAML から命令的で強く型付けされた C# コードに移行します
- コンテナからリソースへ — Aspire はコンテナだけでなく、.NET プロジェクト、実行可能ファイル、パラメーター、クラウドリソースを管理します
- 手動ネットワークから自動サービス検知へ — Aspire は自動的にサービス検知と接続文字列を構成します
- 開発ギャップから統合体験へ — Aspire はダッシュボード、テレメトリー、デバッグ統合を提供します
- スタートアップオーケストレーションの違い — Docker Compose の
depends_onはスタートアップ順序を制御しますが、Aspire のWithReferenceはサービス検知のみを構成します。スタートアップ順序にはWaitForを使用してください
詳細な API マッピングについては、Docker Compose to Aspire AppHost API reference を参照してください。
一般的な移行パターン
Section titled “一般的な移行パターン”このセクションでは、Docker Compose から Aspire に移行する際に遭遇する可能性のある実際の移行シナリオを示します。各パターンは、完全な Docker Compose の例とそれに対応する正確な Aspire の例を示しています。
マルチサービス Web アプリケーション
Section titled “マルチサービス Web アプリケーション”この例は、フロントエンド、API、データベースを備えた典型的な 3 層アプリケーションを示しています。
Docker Compose の例:
version: '3.8'services: frontend: build: ./frontend ports: - "3000:3000" depends_on: api: condition: service_healthy environment: - API_URL=http://api:5000
api: build: ./api ports: - "5000:5000" depends_on: database: condition: service_healthy environment: - ConnectionStrings__DefaultConnection=Host=database;Database=myapp;Username=postgres;Password=secret healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000/health"] interval: 10s timeout: 3s retries: 3
database: image: postgres:15 environment: - POSTGRES_DB=myapp - POSTGRES_USER=postgres - POSTGRES_PASSWORD=secret volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 3s retries: 3
volumes: postgres_data:Aspire 相当:
var builder = DistributedApplication.CreateBuilder(args);
// 明示的なバージョンと永続ストレージを備えた PostgreSQL を追加var database = builder.AddPostgres("postgres") .WithImageTag("15") .WithDataVolume() .AddDatabase("myapp");
// 適切な依存関係を備えた API プロジェクトを追加var api = builder.AddProject<Projects.MyApp_Api>("api") .WithHttpEndpoint(port: 5000) .WithHttpHealthCheck("/health") .WithReference(database, "DefaultConnection") .WaitFor(database);
// 依存関係を備えたフロントエンドプロジェクトを追加var frontend = builder.AddProject<Projects.MyApp_Frontend>("frontend") .WithHttpEndpoint(port: 3000) .WithReference(api) .WithEnvironment("API_URL", api.GetEndpoint("http")) .WaitFor(api);
builder.Build().Run();import { function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder } from './.aspire/modules/aspire.mjs';
const const builder: IDistributedApplicationBuilder
builder = await function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder();
// 明示的なバージョンと永続ストレージを備えた PostgreSQL を追加const const database: PostgresDatabaseResource
database = (await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addPostgres(name: string, options?: { userName?: string | ParameterResource; password?: string | ParameterResource; port?: number;}): PostgresServerResource (+1 overload)
Adds a PostgreSQL resource to the application model. A container is used for local development.
addPostgres("postgres") .ContainerResource.withImageTag(tag: string): PostgresServerResource
Allows overriding the image tag on a container.
withImageTag("15") .PostgresServerResource.withDataVolume(options?: { name?: string; isReadOnly?: boolean;} | undefined): PostgresServerResource (+1 overload)
Adds a named volume for the data folder to a PostgreSQL container resource.
withDataVolume()) .PostgresServerResource.addDatabase(name: string, options?: { databaseName?: string;} | undefined): PostgresDatabaseResource (+1 overload)
Adds a PostgreSQL database to the application model.
addDatabase("myapp");
// 適切な依存関係を備えた API プロジェクトを追加const const api: ProjectResource
api = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addProject(name: string, projectPath: string, options?: { launchProfileOrOptions?: ProjectResourceOptions;}): ProjectResource (+1 overload)
Adds a .NET project resource
addProject("api", "./MyApp.Api/MyApp.Api.csproj") .ProjectResource.withHttpEndpoint(options?: { port?: number; targetPort?: number; name?: string; env?: string; isProxied?: boolean;} | undefined): ProjectResource (+1 overload)
Adds an HTTP endpoint
withHttpEndpoint({ port?: number | undefined
port: 5000 }) .ProjectResource.withHttpHealthCheck(path?: string, statusCode?: number, endpointName?: string): ProjectResource (+1 overload)
Adds a health check to the resource which is mapped to a specific endpoint.
withHttpHealthCheck("/health") .ProjectResource.withReference(source: EndpointReference | string | uri, connectionName?: string, optional?: boolean, name?: string): ProjectResource (+1 overload)
Adds a reference to another resource
withReference(const database: PostgresDatabaseResource
database, "DefaultConnection") .ProjectResource.waitFor(dependency: IResource | IResourceWithConnectionString, waitBehavior?: WaitBehavior): ProjectResource
Waits for another resource to be ready
waitFor(const database: PostgresDatabaseResource
database);
// 依存関係を備えたフロントエンドプロジェクトを追加const const frontend: ProjectResource
frontend = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addProject(name: string, projectPath: string, options?: { launchProfileOrOptions?: ProjectResourceOptions;}): ProjectResource (+1 overload)
Adds a .NET project resource
addProject("frontend", "./MyApp.Frontend/MyApp.Frontend.csproj") .ProjectResource.withHttpEndpoint(options?: { port?: number; targetPort?: number; name?: string; env?: string; isProxied?: boolean;} | undefined): ProjectResource (+1 overload)
Adds an HTTP endpoint
withHttpEndpoint({ port?: number | undefined
port: 3000 }) .ProjectResource.withReference(source: EndpointReference | string | uri, options?: { connectionName?: string; optional?: boolean; name?: string;} | undefined): ProjectResource (+1 overload)
Adds a reference to another resource
withReference(const api: ProjectResource
api) .ProjectResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ProjectResource
Sets an environment variable
withEnvironment("API_URL", const api: ProjectResource
api.ProjectResource.getEndpoint(name: string): EndpointReference
Gets an endpoint reference
getEndpoint("http")) .ProjectResource.waitFor(dependency: IResource | IResourceWithConnectionString, waitBehavior?: WaitBehavior): ProjectResource
Waits for another resource to be ready
waitFor(const api: ProjectResource
api);
await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.build(): DistributedApplication
Builds the distributed application
build().DistributedApplication.run(cancellationToken?: cancellationToken): void
Runs the distributed application
run();主な違いの説明:
- Build 対 プロジェクト — Docker Compose の
build:サービスは .NET アプリのAddProject<T>()になり、コンテナ内ではなく直接実行します - ポート — どちらの例もポート (3000 と 5000) を明示的にマップします
- スタートアップ順序 — Docker Compose は正常性チェック条件付きの
depends_onを使用します。Aspire はスタートアップ順序にWaitFor()を使用します - サービス検知 —
WithReference()はサービス検知と接続文字列のみを構成します。スタートアップ順序を制御しません - 接続文字列 — デフォルトでは、
WithReference(database)はAddDatabase()のリソース名を使用してConnectionStrings__myappを提供します。DefaultConnectionなどの異なる名前に一致させるには、名前付き参照を使用します:.WithReference(database, "DefaultConnection") - ボリューム —
WithDataVolume()は明示的に呼び出す必要があります。自動的ではありません - イメージバージョン —
WithImageTag("15")は PostgreSQL をバージョン 15 にピン止めします
コンテナベースのサービス
Section titled “コンテナベースのサービス”この例は、既存のコンテナイメージと Dockerfile ビルドサービスの混在をオーケストレーションしています。
Docker Compose の例:
version: '3.8'services: web: build: . ports: - "8080:8080" depends_on: redis: condition: service_started postgres: condition: service_healthy environment: - REDIS_URL=redis://redis:6379 - DATABASE_URL=postgresql://postgres:secret@postgres:5432/main
redis: image: redis:7 ports: - "6379:6379"
postgres: image: postgres:15 environment: POSTGRES_PASSWORD: secret volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready"] interval: 10s
volumes: postgres_data:Aspire 相当:
var builder = DistributedApplication.CreateBuilder(args);
// 明示的なバージョンを備えたバッキングサービスを追加var redis = builder.AddRedis("redis") .WithImageTag("7") .WithHostPort(6379);
var postgres = builder.AddPostgres("postgres") .WithImageTag("15") .WithDataVolume() .AddDatabase("main");
// Dockerfile から Web アプリをビルド (Docker Compose の "build: ." に対応)var web = builder.AddDockerfile("web", ".") .WithHttpEndpoint(port: 8080, targetPort: 8080) .WithReference(redis) .WithReference(postgres) .WaitFor(redis) .WaitFor(postgres);
builder.Build().Run();import { function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder } from './.aspire/modules/aspire.mjs';
const const builder: IDistributedApplicationBuilder
builder = await function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder();
// 明示的なバージョンを備えたバッキングサービスを追加const const redis: RedisResource
redis = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addRedis(name: string, options?: { port?: number; password?: string | ParameterResource;}): RedisResource (+1 overload)
Adds a Redis container to the application model.
addRedis("redis") .ContainerResource.withImageTag(tag: string): RedisResource
Allows overriding the image tag on a container.
withImageTag("7") .RedisResource.withHostPort(port: number | null): RedisResource
Configures the host port that the Redis resource is exposed on instead of using randomly assigned port.
withHostPort(6379);
const const postgres: PostgresDatabaseResource
postgres = (await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addPostgres(name: string, options?: { userName?: string | ParameterResource; password?: string | ParameterResource; port?: number;}): PostgresServerResource (+1 overload)
Adds a PostgreSQL resource to the application model. A container is used for local development.
addPostgres("postgres") .ContainerResource.withImageTag(tag: string): PostgresServerResource
Allows overriding the image tag on a container.
withImageTag("15") .PostgresServerResource.withDataVolume(options?: { name?: string; isReadOnly?: boolean;} | undefined): PostgresServerResource (+1 overload)
Adds a named volume for the data folder to a PostgreSQL container resource.
withDataVolume()) .PostgresServerResource.addDatabase(name: string, options?: { databaseName?: string;} | undefined): PostgresDatabaseResource (+1 overload)
Adds a PostgreSQL database to the application model.
addDatabase("main");
// Dockerfile から Web アプリをビルド (Docker Compose の "build: ." に対応)const const web: ContainerResource
web = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addDockerfile(name: string, contextPath: string, options?: { dockerfilePath?: string; stage?: string;}): ContainerResource (+1 overload)
Adds a Dockerfile to the application model that can be treated like a container resource.
addDockerfile("web", ".") .ContainerResource.withHttpEndpoint(options?: { port?: number; targetPort?: number; name?: string; env?: string; isProxied?: boolean;} | undefined): ContainerResource (+1 overload)
Adds an HTTP endpoint
withHttpEndpoint({ port?: number | undefined
port: 8080, targetPort?: number | undefined
targetPort: 8080 }) .ContainerResource.withReference(source: EndpointReference | string | uri, options?: { connectionName?: string; optional?: boolean; name?: string;} | undefined): ContainerResource (+1 overload)
Adds a reference to another resource
withReference(const redis: RedisResource
redis) .ContainerResource.withReference(source: EndpointReference | string | uri, options?: { connectionName?: string; optional?: boolean; name?: string;} | undefined): ContainerResource (+1 overload)
Adds a reference to another resource
withReference(const postgres: PostgresDatabaseResource
postgres) .ContainerResource.waitFor(dependency: IResource | IResourceWithConnectionString, waitBehavior?: WaitBehavior): ContainerResource
Waits for another resource to be ready
waitFor(const redis: RedisResource
redis) .ContainerResource.waitFor(dependency: IResource | IResourceWithConnectionString, waitBehavior?: WaitBehavior): ContainerResource
Waits for another resource to be ready
waitFor(const postgres: PostgresDatabaseResource
postgres);
await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.build(): DistributedApplication
Builds the distributed application
build().DistributedApplication.run(cancellationToken?: cancellationToken): void
Runs the distributed application
run();主な違いの説明:
- イメージバージョン —
WithImageTag()で明示的に指定して Docker Compose と一致させます - Dockerfile ビルド — Docker Compose の
build: .はAddDockerfile("web", ".")にマップしており、Dockerfile からコンテナイメージをビルドします。Docker Compose でimage:を使用する事前ビルドイメージにはAddContainer()を使用します - ポート —
WithHostPort()は静的ホストポートにマップしており、なければ Aspire がランダムポートを割り当てます - ボリューム —
WithDataVolume()は明示的に呼び出す必要があります - スタートアップ順序 —
WaitFor()はスタートアップ順序を制御し、Docker Compose のdepends_onの条件に似ています - 接続文字列 —
WithReference()は Aspire フォーマットの接続文字列 (ConnectionStrings__*) を提供しており、URL フォーマットの変数ではありません
環境変数と構成
Section titled “環境変数と構成”この例は異なる構成管理アプローチを示しています。
Docker Compose アプローチ:
services: app: image: myapp:latest environment: - DATABASE_URL=postgresql://user:pass@db:5432/myapp - REDIS_URL=redis://cache:6379 - API_KEY=${API_KEY} - LOG_LEVEL=infoAspire アプローチ:
var builder = DistributedApplication.CreateBuilder(args);
// シークレット用の外部パラメーターを追加var apiKey = builder.AddParameter("apiKey", secret: true);
var database = builder.AddPostgres("db") .AddDatabase("myapp");
var cache = builder.AddRedis("cache");
var app = builder.AddContainer("app", "myapp", "latest") .WithReference(database) .WithReference(cache) .WithEnvironment("API_KEY", apiKey) .WithEnvironment("LOG_LEVEL", "info");
builder.Build().Run();import { function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder } from './.aspire/modules/aspire.mjs';
const const builder: IDistributedApplicationBuilder
builder = await function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder();
// シークレット用の外部パラメーターを追加const const apiKey: ParameterResource
apiKey = const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addParameter(name: string, options?: { value?: string; publishValueAsDefault?: boolean; secret?: boolean;}): ParameterResource (+1 overload)
Adds a parameter resource
addParameter("apiKey", { secret?: boolean | undefined
secret: true });
const const database: PostgresDatabaseResource
database = (await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addPostgres(name: string, options?: { userName?: string | ParameterResource; password?: string | ParameterResource; port?: number;}): PostgresServerResource (+1 overload)
Adds a PostgreSQL resource to the application model. A container is used for local development.
addPostgres("db")) .PostgresServerResource.addDatabase(name: string, options?: { databaseName?: string;} | undefined): PostgresDatabaseResource (+1 overload)
Adds a PostgreSQL database to the application model.
addDatabase("myapp");
const const cache: RedisResource
cache = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addRedis(name: string, options?: { port?: number; password?: string | ParameterResource;}): RedisResource (+1 overload)
Adds a Redis container to the application model.
addRedis("cache");
const const app: ContainerResource
app = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addContainer(name: string, image: AddContainerOptions): ContainerResource
Adds a container resource to the application.
addContainer("app", { AddContainerOptions.image: string
image: "myapp", AddContainerOptions.tag: string
tag: "latest" }) .ContainerResource.withReference(source: EndpointReference | string | uri, options?: { connectionName?: string; optional?: boolean; name?: string;} | undefined): ContainerResource (+1 overload)
Adds a reference to another resource
withReference(const database: PostgresDatabaseResource
database) .ContainerResource.withReference(source: EndpointReference | string | uri, options?: { connectionName?: string; optional?: boolean; name?: string;} | undefined): ContainerResource (+1 overload)
Adds a reference to another resource
withReference(const cache: RedisResource
cache) .ContainerResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ContainerResource
Sets an environment variable
withEnvironment("API_KEY", const apiKey: ParameterResource
apiKey) .ContainerResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ContainerResource
Sets an environment variable
withEnvironment("LOG_LEVEL", "info");
await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.build(): DistributedApplication
Builds the distributed application
build().DistributedApplication.run(cancellationToken?: cancellationToken): void
Runs the distributed application
run();var dbPassword = builder.AddParameter("dbPassword", secret: true);
var db = builder.AddPostgres("db", password: dbPassword) .AddDatabase("myapp");
var app = builder.AddContainer("app", "myapp", "latest") .WithReference(db) .WithEnvironment(context => { context.EnvironmentVariables["DATABASE_URL"] = ReferenceExpression.Create( $"postgresql://postgres:{dbPassword}@db:5432/myapp"); context.EnvironmentVariables["REDIS_URL"] = "redis://cache:6379"; });const dbPassword = builder.addParameter("dbPassword", { secret: true });
const db = (await builder.addPostgres("db", { password: dbPassword })) .addDatabase("myapp");
const app = await builder.addContainer("app", "myapp:latest") .withReference(db) .withEnvironment("DATABASE_URL", builder.createReferenceExpression`postgresql://postgres:${dbPassword}@db:5432/myapp`) .withEnvironment("REDIS_URL", "redis://cache:6379");カスタムボリュームとバインドマウント
Section titled “カスタムボリュームとバインドマウント”Docker Compose の例:
version: '3.8'services: app: image: myapp:latest volumes: - app_data:/data - ./config:/app/config:ro
worker: image: myworker:latest volumes: - app_data:/shared
volumes: app_data:Aspire 相当:
var builder = DistributedApplication.CreateBuilder(args);
// データ共有用の名前付きボリュームを作成var appData = builder.AddVolume("app-data");
var app = builder.AddContainer("app", "myapp", "latest") .WithVolume(appData, "/data") .WithBindMount("./config", "/app/config", isReadOnly: true);
var worker = builder.AddContainer("worker", "myworker", "latest") .WithVolume(appData, "/shared");
builder.Build().Run();import { function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder } from './.aspire/modules/aspire.mjs';
const const builder: IDistributedApplicationBuilder
builder = await function createBuilder(): IDistributedApplicationBuilder
Creates a new distributed application builder
createBuilder();
const const app: ContainerResource
app = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addContainer(name: string, image: AddContainerOptions): ContainerResource
Adds a container resource to the application.
addContainer("app", { AddContainerOptions.image: string
image: "myapp", AddContainerOptions.tag: string
tag: "latest" }) .ContainerResource.withVolume(target: string, options?: { name?: string; isReadOnly?: boolean;} | undefined): ContainerResource (+1 overload)
Adds a volume to a container resource.
withVolume("/data", { name?: string | undefined
name: "app-data", isReadOnly?: boolean | undefined
isReadOnly: true }) .ContainerResource.withBindMount(source: string, target: string, options?: { isReadOnly?: boolean;} | undefined): ContainerResource (+1 overload)
Adds a bind mount to a container resource.
withBindMount("./config", "/app/config", { isReadOnly?: boolean | undefined
isReadOnly: true });
const const worker: ContainerResource
worker = await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.addContainer(name: string, image: AddContainerOptions): ContainerResource
Adds a container resource to the application.
addContainer("worker", { AddContainerOptions.image: string
image: "myworker", AddContainerOptions.tag: string
tag: "latest" }) .ContainerResource.withVolume(target: string, options?: { name?: string; isReadOnly?: boolean;} | undefined): ContainerResource (+1 overload)
Adds a volume to a container resource.
withVolume("/shared", { name?: string | undefined
name: "app-data" });
await const builder: IDistributedApplicationBuilder
builder.IDistributedApplicationBuilder.build(): DistributedApplication
Builds the distributed application
build().DistributedApplication.run(cancellationToken?: cancellationToken): void
Runs the distributed application
run();主な違い:
- 名前付きボリューム —
AddVolume()で作成され、コンテナ間で共有されます - バインドマウント — ホストディレクトリアクセス用に
WithBindMount()を使用します
ネットワーキング
Section titled “ネットワーキング”Docker Compose は、サービスのグループを相互に分離するカスタムネットワークをサポートしています:
services: proxy: build: ./proxy networks: - frontend app: build: ./app networks: - frontend - backend db: image: postgres networks: - backend
networks: frontend: backend:Aspire にはカスタムネットワーク分離に相当するものがありません。代わりに、Aspire はすべてのコンテナリソース用の共有コンテナネットワークを自動的に作成し、サービス検知を使用してサービス間通信を管理します。Aspire AppHost 内のすべてのコンテナはリソース名でお互いに到達できます。.NET プロジェクトと実行可能ファイルはホスト上で実行され、注入されたホスト/ポートエンドポイントを通じてコンテナにアクセスします。
Docker Compose から Aspire への正常な移行には体系的なアプローチが必要です。
-
現在のセットアップを評価する
Section titled “現在のセットアップを評価する”移行前に、Docker Compose セットアップをインベントリします:
- サービス — データベース、キャッシュ、API、Web アプリケーションを含むすべてのサービスを識別します
- 依存関係 —
depends_on宣言からサービス依存関係をマップします - データ永続性 — データストレージに使用されるすべてのボリュームとバインドマウントをカタログします
- 環境変数 — すべての構成変数とシークレットをリストします
- 正常性チェック — カスタム正常性チェックコマンドを文書化します
- イメージバージョン — 本番環境で使用される特定のバージョンをメモします
-
Aspire AppHost を作成する
Section titled “Aspire AppHost を作成する”新しい Aspire プロジェクトを作成することから始めます:
Terminal window aspire new aspire-starter -o MyApp -
サービスを段階的に移行する
Section titled “サービスを段階的に移行する”バッキングサービスから始めて、サービスを 1 つずつ移行します:
- PostgreSQL、Redis などのバッキングサービスを追加 し、
WithImageTag()で特定のバージョンを指定します WithDataVolume()を使用して永続ストレージを追加 します (必要な場合)- .NET アプリケーションを変換 して、より優れた統合のために
AddProject<T>()でプロジェクト参照にします - Dockerfile ビルドコンテナを
AddDockerfile()で変換 してbuild:ディレクティブと一致させます - 事前ビルドイメージを
AddContainer()で変換 してimage:ディレクティブと一致させます WithReference()で依存関係を構成 してサービス検知のためにWaitFor()でスタートアップ順序を追加 してdepends_onの動作と一致させます- 環境変数を設定 — 接続文字列フォーマットが異なることに注意してください
- 正常性チェックを移行 —
WithHttpHealthCheck()またはカスタムチェック用WithHealthCheck()を使用します
- PostgreSQL、Redis などのバッキングサービスを追加 し、
-
データ移行を処理する
Section titled “データ移行を処理する”永続データについて:
WithDataVolume()をインテグレーションで自動ボリューム管理に使用しますWithVolume()をデータを永続化する必要があるという名前付きボリュームに使用しますWithBindMount()をホスト直接アクセスが必要な場合のホストディレクトリマウントに使用します
-
テストと検証
Section titled “テストと検証”- Aspire AppHost を開始し、すべてのサービスが正しく開始することを確認します
- ダッシュボードをチェックしてサービスの健全性と接続状態を確認します
- サービス間通信が期待どおりに機能することを検証します
- 接続文字列を検証 — アプリが特定の URL フォーマットを期待する場合、環境変数を調整する必要があるかもしれません
移行のトラブルシューティング
Section titled “移行のトラブルシューティング”一般的な問題と解決策
Section titled “一般的な問題と解決策”接続文字列フォーマットの不一致
Section titled “接続文字列フォーマットの不一致”Aspire は URL フォーマット (postgresql:// または redis://) ではなく、.NET スタイルの接続文字列 (ConnectionStrings__*) を生成します。
解決策: アプリケーションが特定の URL フォーマットを期待する場合は、WithEnvironment() を使用して手動で構築してください:
var dbPassword = builder.AddParameter("dbPassword", secret: true);
var postgres = builder.AddPostgres("db", password: dbPassword) .AddDatabase("myapp");
var app = builder.AddContainer("app", "myapp", "latest") .WithReference(postgres) .WithEnvironment(context => { context.EnvironmentVariables["DATABASE_URL"] = ReferenceExpression.Create( $"postgresql://postgres:{dbPassword}@db:5432/myapp"); });const dbPassword = builder.addParameter("dbPassword", { secret: true });
const postgres = (await builder.addPostgres("db", { password: dbPassword })) .addDatabase("myapp");
const app = await builder.addContainer("app", "myapp:latest") .withReference(postgres) .withEnvironment("DATABASE_URL", builder.createReferenceExpression`postgresql://postgres:${dbPassword}@db:5432/myapp`);サービススタートアップ順序の問題
Section titled “サービススタートアップ順序の問題”WithReference() はサービス検知のみを構成し、スタートアップ順序は構成しません。
解決策: 依存関係が準備できていることを確認するために WaitFor() を使用してください:
var api = builder.AddProject<Projects.Api>("api") .WithReference(database) // サービス検知 .WaitFor(database); // スタートアップ順序const api = await builder.addProject("api", "./Api/Api.csproj", "https") .withReference(database) // サービス検知 .waitFor(database); // スタートアップ順序ボリュームマウントの問題
Section titled “ボリュームマウントの問題”- バインドマウントにはパス解決の問題を回避するため絶対パスを使用してください
- ホストディレクトリが存在し、適切なアクセス許可を持つことを確認してください
- データベースインテグレーション用に
WithDataVolume()を使用してください — これは明示的に呼び出す必要があります
Aspire はデフォルトでランダムポートを自動的に割り当てます。
解決策: 静的ポートマッピングに WithHostPort() または WithHttpEndpoint(port:) を使用してください:
var redis = builder.AddRedis("cache") .WithHostPort(6379);const redis = await builder.addRedis("cache") .withHostPort(6379);正常性チェック移行
Section titled “正常性チェック移行”Docker Compose の正常性チェックはシェルコマンドを使用します。Aspire インテグレーション (PostgreSQL および Redis など) には組み込み正常性チェックが自動的に含まれています。カスタム正常性チェックについて、Aspire はリソースタイプに応じて異なるアプローチを提供します。
解決策: HTTP エンドポイント付きリソースについて、WithHttpHealthCheck() を使用してください:
var api = builder.AddProject<Projects.Api>("api") .WithHttpHealthCheck("/health");const api = await builder.addProject("api", "./Api/Api.csproj", "https") .withHttpHealthCheck("/health");シェルコマンドが必要なカスタムコンテナ正常性チェック (RabbitMQ など) については、カスタム正常性チェックを登録してリソースに関連付けてください:
builder.Services.AddHealthChecks() .AddCheck("rabbitmq-health", () => { // カスタム正常性チェックロジックをここに実装してください。 // 例えば、サービスへの TCP 接続を試みます return HealthCheckResult.Healthy(); });
var rabbit = builder.AddContainer("rabbitmq", "rabbitmq", "4.1.4-management-alpine") .WithHealthCheck("rabbitmq-health");
// WaitFor は登録された正常性チェックを使用してレディネスを決定しますvar app = builder.AddProject<Projects.App>("app") .WaitFor(rabbit);const rabbit = await builder.addContainer("rabbitmq", "rabbitmq", "4.1.4-management-alpine") .withHealthCheck("rabbitmq-health");
// WaitFor は登録された正常性チェックを使用してレディネスを決定しますconst app = await builder.addProject("app", "./App/App.csproj", "https") .waitFor(rabbit);次のステップ
Section titled “次のステップ”Aspire への移行後:
- Aspire インテグレーション を探索してカスタムコンテナ構成を置き換えます
- 正常性チェック を設定してより良い監視を実現します
- 本番環境向けの デプロイメントオプション について学びます
- 分散アプリケーション テスト を検討します
- テレメトリー構成 をレビューして可観測性を実現します