跳转到内容
Docs Try Aspire
Docs Try

Configure resource lifetimes in Aspire

此内容尚不支持你的语言。

Aspire resources support a number of different lifetime modes. For example, the default session lifetime starts a resource when the AppHost starts and shuts it down when the AppHost exits. A persistent lifetime leaves a resource running when the AppHost exits and can reuse the same instance on the next run.

Resource lifetimes apply to containers, executables, and projects. Persistent executable and project lifetimes are experimental in Aspire 13.4. You can use different lifetimes for resources that take time to initialize, need stable local endpoints, should remain available while you restart or rebuild the AppHost, or need to match another resource’s lifetime.

Use the shared lifetime APIs for new code. They support container, executable, and project resources.

A session lifetime creates the resource when the AppHost starts and disposes of it when the AppHost stops. This is the default lifetime for resources, so you usually don’t need to configure it explicitly.

Use session lifetime for resources that should only exist while the AppHost is running, such as local test dependencies, temporary containers, or processes that don’t need stable state across runs. Session resources also default to proxied endpoints, which are available while the AppHost is running.

If you previously configured another lifetime and want to return a resource to the default behavior, call WithSessionLifetime(). For container resources, WithLifetime(ContainerLifetime.Session) is still supported.

A persistent lifetime reuses a previously created resource when possible and doesn’t dispose of it when the AppHost stops. Configure this behavior with WithPersistentLifetime(), or with the existing container-specific WithLifetime(ContainerLifetime.Persistent) API for container resources.

Use persistent lifetime for resources that are expensive to initialize, need stable local endpoints, or should remain available while you restart or rebuild the AppHost. Common examples include databases, message brokers, emulators, long-running executables, and project resources that should continue running after the AppHost exits.

Persistent resources default to proxyless endpoints so a stable local endpoint can remain reachable after the AppHost stops. You can still configure endpoint proxy behavior explicitly. For example, set isProxied: true or IsProxied = true when you need Aspire’s proxy for a specific endpoint, or disable endpoint proxy support when you intentionally want every endpoint on a resource to be proxyless. Persistent executable endpoints must have a concrete port or targetPort; automatically persisted random executable ports aren’t supported.

A parent-process lifetime keeps a resource available across AppHost restarts, but scopes cleanup to a parent process. Configure this behavior with WithParentProcessLifetime(processId).

Use parent-process lifetime for resources that should outlive an individual AppHost run but still be cleaned up when a broader development tool, IDE, or other owning process exits.

Parent-process lifetime resources share persistent resource behavior across AppHost runs. If Aspire detects meaningful configuration changes on a subsequent run, the resource is recreated with the new settings.

The parent process ID must be the valid ID of a running process. Aspire records both the process ID and the process identity timestamp so cleanup follows the specific process instance instead of accidentally matching a reused process ID.

A resource-scoped lifetime configures one resource to use another resource’s effective lifetime. Configure this behavior with WithLifetimeOf(resource).

Use resource-scoped lifetime when a companion resource should follow the lifetime choice of another resource. This is useful for sidecars, helper executables, or child resources that should become persistent only when the resource they support is persistent.

Aspire evaluates the source resource’s lifetime when it prepares the application model, so later lifetime changes to the source resource are reflected by the dependent resource. The source and dependent resources must both support lifetime configuration.

For new code, configure a persistent container with WithPersistentLifetime():

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres")
.WithPersistentLifetime()
.WithDataVolume();
var db = postgres.AddDatabase("inventorydb");
builder.AddProject<Projects.InventoryService>("inventory")
.WithReference(db);
builder.Build().Run();

In the preceding example, the PostgreSQL container persists between AppHost runs, and WithDataVolume() stores database data in a named volume that survives container recreation. The inventory project references the database as normal.

Executable resources can also use persistent lifetimes. Persistent executables are useful for local services that have expensive startup, need stable process identity, or should remain reachable while the AppHost restarts.

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var worker = builder.AddExecutable("worker", "node", "../worker", "server.js")
.WithHttpEndpoint(port: 5050, targetPort: 5050)
.WithPersistentLifetime();
builder.Build().Run();

Configure a concrete port or targetPort for persistent executable endpoints; automatically persisted random executable ports aren’t supported.

Project resources can use persistent lifetimes when you want the project process to continue running after the AppHost exits.

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.ApiService>("api")
.WithPersistentLifetime();
builder.Build().Run();

Persistent project and executable resources are run by Aspire’s orchestrator so it can manage their lifecycle consistently. Persistent project and executable resources don’t support replicas.

Use WithLifetimeOf when a companion resource should follow another resource’s lifetime. This is useful when a sidecar, helper process, or supporting service should become persistent only when its source resource is persistent.

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var database = builder.AddPostgres("postgres")
.WithPersistentLifetime()
.WithDataVolume();
var companion = builder.AddExecutable("companion", "dotnet", "../Companion", "Companion.dll")
.WithLifetimeOf(database);
builder.Build().Run();

The dependent resource’s lifetime is evaluated when Aspire prepares the application model, so later changes to the source resource’s lifetime are reflected by the dependent resource.

Use WithParentProcessLifetime when a resource should survive AppHost restarts but be cleaned up when another process exits. Aspire records the parent process identity instead of retaining a live process handle, so the cleanup scope follows the specific process instance instead of a reused process ID.

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var parentProcessId = int.Parse(builder.Configuration["RESOURCE_PARENT_PROCESS_ID"]!);
var worker = builder.AddExecutable("scoped-worker", "node", "../worker", "server.js")
.WithParentProcessLifetime(parentProcessId);
builder.Build().Run();

The parent process ID must be greater than zero and identify a running process.

The older container-specific lifetime API is still supported. Use WithLifetime(ContainerLifetime.Persistent) to keep a container running across AppHost restarts, or WithLifetime(ContainerLifetime.Session) to explicitly use the default session behavior.

For new code, prefer the shared WithPersistentLifetime() and WithSessionLifetime() APIs because they work consistently across containers, executables, and projects.

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume();
builder.Build().Run();

The Aspire dashboard shows persistent resources with a distinctive pin icon to help you identify them:

Screenshot of the Aspire dashboard showing a persistent resource with a pin icon.

After the AppHost stops, persistent containers continue running and can be seen in your container runtime (such as Docker Desktop):

Screenshot of Docker Desktop showing a persistent RabbitMQ container still running after the AppHost stopped.

By default, persistent containers use a naming pattern that combines:

  • The service name you specify in your AppHost.
  • A postfix based on a hash of the AppHost project path.

This naming scheme ensures that persistent containers are unique to each AppHost project, preventing conflicts when multiple Aspire projects use the same service names.

For example, if you have a service named "postgres" in an AppHost project located at /path/to/MyApp.AppHost, the container name might be postgres-abc123def where abc123def is derived from the project path hash.

For advanced scenarios, you can set a custom container name using the WithContainerName method:

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres")
.WithPersistentLifetime()
.WithContainerName("my-shared-postgres");
builder.Build().Run();

When you specify a custom container name, Aspire first checks if a container with that name already exists. If a container with that name exists and was previously created by Aspire, it follows the normal persistent container behavior and can be automatically recreated if the configuration changes. If a container with that name exists but wasn’t created by Aspire, it won’t be managed or recreated by the AppHost. If no container with the custom name exists, Aspire creates a new one.

Executable and project naming and uniqueness

Section titled “Executable and project naming and uniqueness”

Persistent executable and project resources are scoped to a specific AppHost instance and uniquely identified by their resource name within that scope. Two executable or project resources with the same name in different AppHosts don’t collide with each other; they result in separate process instances.

For persistent containers, use Docker CLI commands, Docker Desktop, or your preferred container management tool to stop and remove the container:

Stop and remove a persistent container
# Stop the container
docker stop my-container-name
# Remove the container
docker rm my-container-name

For persistent executable and project resources, stop the running process with your operating system process manager or terminal tools. You can also stop a persistent resource from the Aspire dashboard if the runtime-specific cleanup option isn’t straightforward.

WithPersistentLifetime() and WithDataVolume() serve different purposes and are often used together. The following table summarizes the behavior of each combination for container resources:

ConfigurationContainer behaviorData behavior
Neither (default)Created on start, destroyed on stopLost every time the AppHost stops
WithPersistentLifetime() onlyStays running between AppHost runsSurvives AppHost restarts, but lost if the container is recreated (config change, pruning, image update)
WithDataVolume() onlyCreated on start, destroyed on stopPersists in a named volume—survives container recreation
Both (recommended for databases)Stays running between AppHost runsPersists in a named volume—survives container recreation

For databases and other stateful services, use both APIs together so you get fast startup (the container stays running) and data safety (a volume protects data even if the container is recreated):

AppHost.cs
var postgres = builder.AddPostgres("postgres")
.WithPersistentLifetime()
.WithDataVolume();

For caches or other ephemeral state, WithPersistentLifetime() alone may be sufficient because losing data on container recreation is acceptable.