ドキュメントAspire を試す
ドキュメント試す

Aspire で外部実行可能ファイルをホストする

Aspire では、AddExecutable メソッドを使用して、プロジェクトと一緒に外部の実行可能アプリケーションをホストできます。この機能は、Node.js アプリケーション、Python スクリプト、特殊な CLI ツールなどの実行可能アプリケーションやツールを分散アプリケーションに統合する必要がある場合に役立ちます。

実行可能リソースを使用する場合

Section titled “実行可能リソースを使用する場合”

実行可能リソースは、次のような場合に使用します:

  • コンテナーではなくホスト上でアプリケーションやツールを直接実行する。
  • コマンドライン ツールやユーティリティをアプリケーションに統合する。
  • 他のリソースが依存する外部プロセスを実行する。
  • ローカル開発サーバーを提供するツールを使って開発する。

一般的な例は次のとおりです:

  • フロントエンド開発サーバー: Vercel CLI や webpack dev server のようなツール。
  • 言語固有のアプリケーション: Node.js アプリ、Python スクリプト、Go アプリケーション。
  • データベース ツール: マイグレーション ユーティリティやデータベース シーダー。
  • ビルド ツール: アセット プロセッサーやコード ジェネレーター。

AddExecutable メソッドでは、リソース名、実行可能ファイルのパス、そして必要に応じてコマンドライン引数と作業ディレクトリが必要です:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// 引数なしの基本的な実行可能ファイル
const nodeApp = await builder.addExecutable("frontend", "node", ".", ["server.js"]);
// コマンドライン引数付きの実行可能ファイル
const pythonApp = await builder.addExecutable("api", "python", ".", ["-m", "uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]);
await builder.build().run();

このコードは、基本的な実行可能リソースの設定方法を示しています。最初の例は Node.js サーバー スクリプトを実行し、2 つ目の例は特定の構成オプションを AddExecutable メソッドに引数として直接渡して、Uvicorn を使用する Python アプリケーションを起動します。

コマンドライン引数は AddExecutable 呼び出しで直接指定でき、リソース依存関係の環境変数も構成できます。実行可能リソースは他のリソースを参照し、その接続情報にアクセスできます。

AddExecutable 呼び出しで引数を指定する

Section titled “AddExecutable 呼び出しで引数を指定する”
apphost.mts
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
();
// 引数を addExecutable で直接指定します
const
const app: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("vercel-dev", "vercel", ".", ["dev", "--listen", "3000"]);

環境変数を使ったリソース依存関係

Section titled “環境変数を使ったリソース依存関係”

他のリソースに依存する引数には、環境変数を使用します:

apphost.mts
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
("cache");
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")).
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("appdb");
const
const app: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("worker", "python", ".", ["worker.py"])
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): ExecutableResource (+1 overload)

Adds a reference to another resource

withReference
(
const redis: RedisResource
redis
) // ConnectionStrings__cache を提供します
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): ExecutableResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgres: PostgresDatabaseResource
postgres
); // ConnectionStrings__appdb を提供します

1 つのリソースが別のリソースに依存している場合、WithReference は依存先リソースの接続詳細を含む環境変数を渡します。たとえば、worker 実行可能ファイルが redispostgres を参照すると、これらのリソースへの接続文字列を含む ConnectionStrings__cache および ConnectionStrings__appdb 環境変数が提供されます。

特定のエンドポイント情報にアクセスする

Section titled “特定のエンドポイント情報にアクセスする”

実行可能ファイルに接続情報を渡す方法をさらに細かく制御するには、次のようにします:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
,
type EndpointProperty = "Url" | "Host" | "IPV4Host" | "Port" | "Scheme" | "TargetPort" | "HostAndPort" | "TlsEnabled"
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
} 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
("cache");
const
const redisEndpoint: EndpointReference
redisEndpoint
= await
const redis: RedisResource
redis
.
ContainerResource.getEndpoint(name: string): EndpointReference

Gets an endpoint reference

getEndpoint
("tcp");
const
const redisHost: EndpointReferenceExpression
redisHost
= await
const redisEndpoint: EndpointReference
redisEndpoint
.
EndpointReference.property(property: EndpointProperty): EndpointReferenceExpression

Gets the specified property expression of the endpoint.

property
(
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
.
type Host: "Host"
Host
);
const
const redisPort: EndpointReferenceExpression
redisPort
= await
const redisEndpoint: EndpointReference
redisEndpoint
.
EndpointReference.property(property: EndpointProperty): EndpointReferenceExpression

Gets the specified property expression of the endpoint.

property
(
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
.
type Port: "Port"
Port
);
const
const app: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("app", "node", ".", ["app.js"])
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): ExecutableResource (+1 overload)

Adds a reference to another resource

withReference
(
const redis: RedisResource
redis
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("REDIS_HOST",
const redisHost: EndpointReferenceExpression
redisHost
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("REDIS_PORT",
const redisPort: EndpointReferenceExpression
redisPort
);

次は、Vercel CLI を使用して、バックエンド API とともにフロントエンド アプリケーションをホストする完全な例です:

apphost.mts
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
();
// バックエンド 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", "./Api/Api.csproj")
.
ProjectResource.withExternalHttpEndpoints(): ProjectResource

Marks existing http or https endpoints on a resource as external.

withExternalHttpEndpoints
();
// Vercel CLI を使用するフロントエンド
const
const frontend: ExecutableResource
frontend
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("vercel-dev", "vercel", ".", ["dev", "--listen", "3000"])
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("API_URL",
const api: ProjectResource
api
.
ProjectResource.getEndpoint(name: string): EndpointReference

Gets an endpoint reference

getEndpoint
("http"))
.
ExecutableResource.withHttpEndpoint(options?: {
port?: number;
targetPort?: number;
name?: string;
env?: string;
isProxied?: boolean;
} | undefined): ExecutableResource (+1 overload)

Adds an HTTP endpoint

withHttpEndpoint
({
port?: number | undefined
port
: 3000,
name?: string | undefined
name
: "http" });
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

実行可能リソースは、他のリソースが参照できる HTTP エンドポイントを公開できます:

apphost.mts
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 frontend: ExecutableResource
frontend
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("webpack-dev", "npx", ".", ["webpack", "serve", "--port", "8080", "--host", "0.0.0.0"])
.
ExecutableResource.withHttpEndpoint(options?: {
port?: number;
targetPort?: number;
name?: string;
env?: string;
isProxied?: boolean;
} | undefined): ExecutableResource (+1 overload)

Adds an HTTP endpoint

withHttpEndpoint
({
port?: number | undefined
port
: 8080,
name?: string | undefined
name
: "http" });
// 別のサービスがフロントエンドを参照できます
const
const e2eTests: ExecutableResource
e2eTests
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("playwright", "npx", ".", ["playwright", "test"])
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("BASE_URL",
const frontend: ExecutableResource
frontend
.
ExecutableResource.getEndpoint(name: string): EndpointReference

Gets an endpoint reference

getEndpoint
("http"));

実行可能ファイルの環境変数を構成します:

apphost.mts
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: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("api", "uvicorn", ".", ["main:app", "--reload", "--host", "0.0.0.0"])
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("DEBUG", "true")
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("LOG_LEVEL", "info")
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): ExecutableResource

Sets an environment variable

withEnvironment
("START_TIME", new
var Date: DateConstructor
new () => Date (+3 overloads)
Date
().
Date.toISOString(): string

Returns a date as a string value in ISO format.

toISOString
());

本番環境へデプロイするには、実行可能リソースをコンテナー化する必要があります。実行可能ファイルをどのようにパッケージ化するかを指定するには、PublishAsDockerFile メソッドを使用します:

apphost.mts
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: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("frontend", "npm", ".", ["start", "--port", "3000"])
.
ExecutableResource.publishAsDockerFile(configure: (obj: ContainerResource) => Promise<void>): ExecutableResource

Publishes an executable as a Docker file

publishAsDockerFile
(async () => {});

PublishAsDockerFile() を呼び出すと、Aspire は発行プロセス中に Dockerfile を生成します。独自の Dockerfile を指定して、この動作をカスタマイズすることもできます:

実行可能ファイルの作業ディレクトリに Dockerfile を作成します:

Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

次に、AppHost でそれを参照します:

apphost.mts
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: ExecutableResource
app
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResource

Adds an executable resource to the application model.

addExecutable
("frontend", "npm", ".", ["start"])
.
ExecutableResource.publishAsDockerFile(configure: (obj: ContainerResource) => Promise<void>): ExecutableResource

Publishes an executable as a Docker file

publishAsDockerFile
(async () => {});

実行可能リソースを扱う際は、次の点を意識してください:

  1. 明示的なパスを使用する: 信頼性を高めるため、可能な場合は実行可能ファイルへの完全パスを使用します。
  2. 依存関係を処理する: WithReference を使用して適切な依存関係を確立します。
  3. 明示的な開始を構成する: 自動的に開始すべきでない実行可能ファイルには WithExplicitStart() を使用します。
  4. デプロイに備える: 本番シナリオでは常に PublishAsDockerFile() を使用します。
  5. 環境を分離する: 機密な構成にはコマンドライン引数ではなく環境変数を使用します。
  6. リソース名を工夫する: 実行可能ファイルの目的が明確に分かる説明的な名前を使用します。