Aspire app lifecycle guide
This guide provides a high-level overview of the lifecycle phases of an Aspire application, from development through local deployment to production release. By using the same AppHost configuration across all phases, you ensure consistency and reduce configuration drift between environments. The example in this guide demonstrates how Aspire orchestrates containerized applications with persistent storage and CI/CD automation using the Docker Integration and GitHub.
App lifecycle
The Aspire application lifecycle consists of three main phases:
- 1
Inner-Loop Development - Local development and debugging with
aspire run - 2
Local Deployment - Deployment to your defined compute environment(s) with
aspire deploy. This example shows containerized deployment to Docker Desktop. - 3
Publish Release (CI/CD) - Automated build & publish pipeline. This example shows using GitHub Actions to build and push images and publish release artifacts for deployment later.
Each phase uses the same AppHost configuration but serves different purposes in the development and deployment workflows.
Example
The following example uses a C# AppHost, but the same lifecycle applies to TypeScript AppHosts.
Consider this example. You have a distributed application that consists of a Blazor web project that relies on a SQL Server database with a persistent data volume as well as a persistent writable file volume to capture user file uploads. You want to distribute your Blazor app as a Docker container image via the GitHub Container Registry. You need the Aspire.Hosting.Docker and Aspire.Hosting.SqlServer integrations.
var builder = DistributedApplication.CreateBuilder(args);
// Add Docker Compose environment
var compose = builder.AddDockerComposeEnvironment("volumemount-env")
.WithProperties(env =>
{
env.DashboardEnabled = true;
})
.ConfigureComposeFile(composeFile =>
{
// Add the blazor file volume to the top-level volumes section
composeFile.AddVolume(new Volume
{
Name = "volumemount-blazor-uploads",
Driver = "local"
});
});
// Add container registry
var endpoint = builder.AddParameter("registry-endpoint");
var repository = builder.AddParameter("registry-repository");
builder.AddContainerRegistry("container-registry", endpoint, repository);
//Add SQL Server with data volume
var sqlPassword = builder.AddParameter("sqlserver-password", secret: true);
var sqlserver = builder.AddSqlServer("sqlserver", password: sqlPassword)
.WithDataVolume("volumemount-sqlserver-data")
.WithLifetime(ContainerLifetime.Persistent);
var sqlDatabase = sqlserver.AddDatabase("sqldb");
//Add the Blazor web app with reference to the database
//Deploy as a docker image with a volume mount for user upload files
var blazorweb = builder.AddProject<Projects.VolumeMount_BlazorWeb>("blazorweb")
.WithExternalHttpEndpoints()
.WithReference(sqlDatabase)
.WaitFor(sqlDatabase)
//Deploy the Web project as a Docker Compose service with a volume mount for files
.PublishAsDockerComposeService((resource, service) =>
{
service.AddVolume(new Volume
{
Name = "volumemount-blazor-uploads",
Source = "volumemount-blazor-uploads",
Target = "/app/wwwroot/uploads",
Type = "volume",
ReadOnly = false
});
// Override the entrypoint to allow write permissions to the volume
// then run the default entrypoint as app user
service.User = "root";
service.Command = new List<string>
{
"/bin/sh",
"-c",
"chown -R app:app /app/wwwroot/uploads && chmod -R 755 /app/wwwroot/uploads && exec su app -c 'dotnet /app/VolumeMount.BlazorWeb.dll'"
};
});
builder.Build().Run();
Phase 1: Inner-Loop Development
What is aspire run?
The aspire run command starts your Aspire application in development mode. This is the inner-loop development experience where you write code, test changes, and debug your application locally.
When you run aspire run:
- 1
Aspire dashboard launches - A web-based dashboard starts, and its URL (often an HTTPS login URL like
https://localhost:<port>/login?...) is printed to the console. - 2
Resources start - All resources defined in your AppHost are orchestrated.
- 3
Live debugging - You can attach debuggers, set breakpoints, and modify code with hot reload.
- 4
Telemetry & logs - Dashboard provides real-time logs, metrics, and distributed traces.
This command searches the current directory structure for AppHost projects to build and run:
aspire run
The console will display the dashboard URL with a login token:
Dashboard: https://localhost:17244/login?t=9db79f2885dae24ee06c6ef10290b8b2
Logs: /home/vscode/.aspire/cli/logs/apphost-5932-2025-08-25-18-37-31.log
Press CTRL+C to stop the apphost and exit.
In the example above, when resources start with the run command:
- SQL Server container starts in Docker with persistent volume
- Web project runs as a local process (not containerized)
- Database is automatically created and migrated (containerized)
Phase 2: Local Deployment
What is aspire deploy?
The aspire deploy command creates a fully containerized deployment of your application in the compute environment(s) you define. This simulates a production-like environment on your local machine. In this example, local containers and volumes are created on Docker Desktop using the Docker Integration. It requires all parameters to be set.
Note
Aspire will prompt you for parameters the first time you deploy and save them for later use. For more info, see External Parameters.
When you run aspire deploy Aspire will:
- 1
Build and push container images for projects
- 2
Generate
docker-compose.yamlin./aspire-output/directory - 3
Start all containers using Docker Compose
- 4
Create and mount persistent volumes
In this example, the following gets deployed:
Containers:
aspire-volumemount-env- Docker Compose stacksqlserver- SQL Server with persistent data volumeblazorweb- Blazor Web app with persistent file uploads volumevolumemount-env-dashboard- Monitoring dashboard
Volumes:
volumemount-sqlserver-data- Stores database files (.mdf,.ldf)volumemount-blazor-uploads- Stores user-uploaded images
Note
You will need a GitHub personal access token to access the GitHub Container Registry. See Authenticating to the GitHub Container Registry
You can login to your GitHub Container Registry before deploying.
export GITHUB_TOKEN=
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
aspire deploy
Phase 3: Publish Release (CI/CD)
You can create a workflow that automates the process of building and pushing the image, and publishing of deployment artifacts using the Aspire CLI in a CI/CD pipeline. The Aspire CLI can be used to build your app, push images, and publish artifacts. This allows you to deploy the app later via standard Docker Compose.
In this example, the workflow runs on every push to main, does a checkout, and then performs these steps:
- 1
Setup Environment - Install required SDKs
- 2
Install Aspire CLI - Install the Aspire CLI
- 3
Build and Push Container Images - Build app and push image to GitHub Container Registry with
aspire do push - 4
Publish Docker Compose Artifacts - Generate deployment files with
aspire publish - 5
Upload Artifacts - Store deployment files for download
Step 1: Setup Environment
# Required for C# AppHost projects
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
Step 2: Install Aspire CLI
- name: Install Aspire CLI
run: |
echo "Installing Aspire CLI from install script..."
curl -sSL https://aspire.dev/install.sh | bash
echo "$HOME/.aspire/bin" >> $GITHUB_PATH
Step 3. Build App, Create & Push Image to GHCR
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push images with Aspire
env:
Parameters__registry_endpoint: ghcr.io
Parameters__registry_repository: your-org/your-repo
run: aspire do push
Note
Replace your-org/your-repo with your actual GitHub organization and repository name, or use ${{ github.repository_owner }}/${{ github.event.repository.name }} for automatic values. Values must be lowercase.
The aspire do push command does the following:
- Analyzes your AppHost configuration
- Restores dependencies and builds the project
- Builds Docker container images for project resources
- Tags images with configured registry endpoint and repository
- Pushes images to GitHub Container Registry (ghcr.io)
- Uses parameters defined in
AppHost.cs:- Environment
Parameters__registry_endpointmaps toregistry-endpointparameter - Environment
Parameters__registry_repositorymaps toregistry-repositoryparameter
- Environment
Step 4: Publish Docker Compose Artifacts
- name: Prepare Docker Compose with Aspire
run: |
aspire publish \
--project VolumeMount.AppHost/VolumeMount.AppHost.csproj \
--output-path ./aspire-output
Note
The --project flag is needed when your AppHost isn't in the current directory.
The aspire publish command does the following:
- Analyzes your AppHost configuration
- Generates
docker-compose.yamlfile with all service definitions - Creates
.envtemplate file for environment variables - Packages configuration needed for deployment
- Outputs artifacts to
./aspire-output/directory
Step 5: Upload Deployment Artifacts
- name: Upload Aspire artifacts
uses: actions/upload-artifact@v4
with:
name: aspire-deployment-files
path: ./aspire-output/
retention-days: 30
include-hidden-files: true
In this example, artifacts are available for download from the Actions workflow run for 30 days. Hidden files are included so that the .env file is also available in the artifacts.
Deploying to Production
After the workflow completes, you have everything needed for production deployment:
- 1
Download Artifacts from GitHub Actions workflow run:
docker-compose.yaml- Complete service definitions.env- Environment variable template
- 2
Configure Environment Variables in
.env. For example:BLAZORWEB_IMAGE=ghcr.io/bethmassi/volumemount/blazorweb:latest BLAZORWEB_PORT=8080 SQLSERVER_PASSWORD=YourSecurePassword - 3
Deploy with Docker Compose:
docker compose up -d - 4
Verify Deployment:
docker compose ps docker compose logs -f
Lifecycle Summary
| Phase | Command | Purpose | Environment | App | Database |
|---|---|---|---|---|---|
| Development | aspire run |
Inner-loop coding & debugging | Local machine | Local process | Container |
| Local Deploy | aspire deploy |
Test containerized app locally | Registered compute environment (i.e. Docker Desktop) | Container | Container |
| Release | CI/CD workflow (i.e. GitHub Actions) | Publish to staging/ production | Cloud/Server | Container | Container |
Tip
This example uses a C# AppHost, but the same lifecycle workflow applies to TypeScript AppHosts. Replace .csproj references with your apphost.ts path as needed.
The AppHost is the single source of truth for your application architecture. Each phase above uses the exact same AppHost configuration. This eliminates configuration drift between development and deployment. It defines things your distributed application needs like:
- Services & Dependencies - Projects, containers, and their relationships
- Configuration - Connection strings, secrets, and parameters
- Volumes - Persistent storage for databases and files
- Networking - Endpoints, ports, and service communication
- Deployment - Container registry, image tags, and publish settings
For more information, see AppHost configuration.
Next steps
- Learn more about Service discovery
- Explore Telemetry options
- Understand Health checks