दस्तावेज़आज़माएं

Host external executables in Aspire

यह कंटेंट अभी तक आपकी भाषा में उपलब्ध नहीं है।

In Aspire, you can host external executable applications alongside your projects using the AddExecutable method. This capability is useful when you need to integrate executable applications or tools into your distributed application, such as Node.js applications, Python scripts, or specialized CLI tools.

Use executable resources when you need to:

  • Run applications or tools directly on the host instead of in a container.
  • Integrate command-line tools or utilities into your application.
  • Run external processes that other resources depend on.
  • Develop with tools that provide local development servers.

Common examples include:

  • Frontend development servers: Tools like Vercel CLI or webpack dev server.
  • Language-specific applications: Node.js apps, Python scripts, or Go applications.
  • Database tools: Migration utilities or database seeders.
  • Build tools: Asset processors or code generators.

The AddExecutable method requires a resource name, the executable path, and optionally command-line arguments and a working directory:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// Basic executable without arguments
const nodeApp = await builder.addExecutable("frontend", "node", ".", ["server.js"]);
// Executable with command-line arguments
const pythonApp = await builder.addExecutable("api", "python", ".", ["-m", "uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]);
await builder.build().run();

This code demonstrates setting up a basic executable resource. The first example runs a Node.js server script, while the second starts a Python application using Uvicorn with specific configuration options passed as arguments directly to the AddExecutable method.

Resource dependencies and environment configuration

Section titled “Resource dependencies and environment configuration”

You can provide command-line arguments directly in the AddExecutable call and configure environment variables for resource dependencies. Executable resources can reference other resources and access their connection information.

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
();
// Arguments provided directly in 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"]);

Resource dependencies with environment variables

Section titled “Resource dependencies with environment variables”

For arguments that depend on other resources, use environment variables:

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
) // Provides 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
); // Provides ConnectionStrings__appdb

When one resource depends on another, WithReference passes along environment variables containing the dependent resource’s connection details. For example, the worker executable’s reference to redis and postgres provides it with the ConnectionStrings__cache and ConnectionStrings__appdb environment variables, which contain connection strings to these resources.

For more control over how connection information is passed to your executable:

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
);

Here’s a complete example using the Vercel CLI to host a frontend application with a backend 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
();
// Backend 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
();
// Frontend with 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
();

Executable resources can expose HTTP endpoints that other resources can reference:

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" });
// Another service can reference the frontend
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"));

Configure environment variables for your executable:

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
());

withEnvironment API unification in Aspire 13.3

Section titled “withEnvironment API unification in Aspire 13.3”

Aspire 13.3 unified non-C# AppHost environment assignment behind a single withEnvironment(name, value) pattern. The public TypeScript API accepts plain strings, reference expressions, endpoint references, parameter resources, supported resources that expose connection strings, expression values, and awaitable forms of supported values.

When upgrading to Aspire 13.3, replace every earlier per-kind environment helper call with withEnvironment(name, value). The 13.3 TypeScript SDK doesn’t generate compatibility aliases for those helpers.

For production deployment, executable resources need to be containerized. Use the PublishAsDockerFile method to specify how the executable should be packaged:

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 () => {});

When you call PublishAsDockerFile(), Aspire generates a Dockerfile during the publish process. You can customize this by providing your own Dockerfile:

Create a Dockerfile in your executable’s working directory:

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

Then reference it in your 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 () => {});

When working with executable resources:

  1. Use explicit paths: For better reliability, use full paths to executables when possible.
  2. Handle dependencies: Use WithReference to establish proper dependency relationships.
  3. Configure explicit start: Use WithExplicitStart() for executables that shouldn’t start automatically.
  4. Prepare for deployment: Always use PublishAsDockerFile() for production scenarios.
  5. Environment isolation: Use environment variables rather than command-line arguments for sensitive configuration.
  6. Resource naming: Use descriptive names that clearly identify the executable’s purpose.