
Aspire Deployment
- 121 installs
- 76 repo stars
- Updated August 4, 2026
- microsoft/aspire-skills
aspire-deployment is an agent skill that deploys Aspire apps from AppHost models to Docker, Kubernetes, Azure, or AWS via aspire CLI.
About
The aspire-deployment skill publishes, previews, validates, deploys, and tears down Aspire application deployments starting from the AppHost model. It wins routing precedence over generic cloud skills when Aspire markers exist such as AppHost projects, aspire.config.json, or distributed application builder APIs. The workflow orients with aspire ls and aspire describe, clarifies deployment targets including Docker Compose, Kubernetes, Azure Container Apps, App Service, AKS, or AWS, searches aspire docs before editing deployment code, and prefers native aspire publish, aspire deploy, aspire destroy, and aspire do commands. Target-specific references load only for the chosen platform. Agents ask where to deploy when multiple or zero targets exist, confirm before creating billable cloud resources unless deploy-now intent is explicit, and keep Azure paths Aspire-native rather than separate Bicep workflows. Handoffs route missing AppHosts to aspire-init or aspireify and monitoring to aspire-monitoring. Use when deploying Aspire apps, generating Kubernetes or Compose artifacts, publishing to Azure Container Apps, or tearing down deployed resources.
- Routes deployment from AppHost model with Aspire CLI precedence over generic cloud tools.
- Supports Docker Compose, Kubernetes, Azure Container Apps, App Service, AKS, and AWS targets.
- Requires aspire docs search before inventing deployment APIs or package names.
- Asks deployment target and confirms before provisioning billable cloud resources.
- Handoffs to aspire-init, aspireify, and aspire-monitoring for related workflows.
Aspire Deployment by the numbers
- 121 all-time installs (skills.sh)
- +19 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #516 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
aspire-deployment capabilities & compatibility
- Capabilities
- apphost discovery and target routing precedence · aspire docs search before deployment code change · native aspire publish deploy destroy commands · multi target reference loading for cloud platfor · billable resource confirmation and handoff rules
- Works with
- azure · aws · kubernetes · docker
- Use cases
- devops · ci cd
What aspire-deployment says it does
Aspire deployment starts from the AppHost model.
This skill wins over generic cloud deployment skills when both conditions are true
Do not invent package names, builder methods, overloads, or deployment commands.
npx skills add https://github.com/microsoft/aspire-skills --skill aspire-deploymentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 121 |
|---|---|
| repo stars | ★ 76 |
| Last updated | August 4, 2026 |
| Repository | microsoft/aspire-skills ↗ |
How do I deploy or publish an Aspire application to Docker Compose, Kubernetes, Azure, or AWS?
Deploy Aspire apps from AppHost models to Docker Compose, Kubernetes, Azure, or AWS using aspire CLI commands.
Who is it for?
Teams with Aspire AppHost projects who need target-specific publish and deploy workflows.
Skip if: Skip for repos without Aspire markers or when only scaffolding a new AppHost is needed.
When should I use this skill?
User asks to deploy Aspire app, publish artifacts, deploy to Azure Container Apps, or tear down deployment.
What you get
Published deployment artifacts and optionally provisioned resources via aspire publish and aspire deploy.
Files
Aspire Deployment
Use this skill when the task is to publish, preview, validate, deploy, or tear down an Aspire application deployment. This skill owns Aspire deployment routing. Do not start with a generic Azure, Docker, Kubernetes, Helm, or Bicep workflow until you have checked whether the workspace is an Aspire app.
Aspire deployment starts from the AppHost model. Treat aspire deploy, aspire publish, aspire destroy, aspire do, and the deployment environment resources in the AppHost as the primary path.
Keep this as one skill with target-specific references. Load only the reference files that match the target you discover or the user requests.
Routing precedence
This skill wins over generic cloud deployment skills when both conditions are true:
1. The user asks to deploy, publish, generate deployment artifacts, create Bicep/Helm/Compose/CDK output, host on Azure or AWS, deploy to Azure or AWS, deploy to Kubernetes, deploy to Docker Compose, tear down deployed resources, or validate a deployment. 2. The workspace has Aspire markers:
- Aspire workspace configuration
- C# or TypeScript AppHost files
- an AppHost project
- AppHost code using Aspire distributed application builder APIs
If Aspire markers are present but this skill was not automatically invoked, switch to this skill before continuing. Prefer Aspire CLI commands such as aspire ls, aspire config list, aspire ps, and aspire describe for workspace orientation.
Guiding principles
Use Aspire docs before changing deployment code
Before adding target packages, editing the AppHost, or using an unfamiliar deployment API, use Aspire docs:
aspire docs search "deploy with Aspire"
aspire docs search "Docker Compose deployment"
aspire docs search "Kubernetes deployment"
aspire docs search "Azure Container Apps deployment"
aspire docs search "Azure App Service deployment"
aspire docs search "Azure Kubernetes Service deployment"
aspire docs get "deploy-to-azure-kubernetes-service-aks"
aspire docs get "<slug-from-search-results>"When you need exact C# or TypeScript API shape, use API docs too. Search both languages when you are not sure which AppHost language the repo uses:
aspire docs api search "<deployment API or concept>" --language csharp
aspire docs api search "<deployment API or concept>" --language typescript
aspire docs api get "<id-from-api-search>"Do not invent package names, builder methods, overloads, or deployment commands. API shapes differ between C# and TypeScript AppHosts.
Prefer Aspire-native deployment
Use Aspire deployment targets and CLI commands first:
aspire publish --list-steps
aspire deploy --list-steps
aspire publish
aspire deploy
aspire destroy
aspire do <step>Use target-specific tooling only after Aspire has generated artifacts or when the target docs call for it:
- Docker Compose: inspect generated
aspire-output/docker-compose.yamland.env*; Aspire can also rundocker compose upthroughaspire deploy. - Kubernetes: inspect generated Helm chart output; use Helm/kubectl when applying published artifacts yourself.
- Azure: use
aspire add <azure-target>,aspire publish, andaspire deploythrough the AppHost deployment environment. - AWS: use
aspire add awsto add the integration, inspect generated CDK/CloudFormation output, and follow the AWS integrations repository guidance.
Ask where to deploy only when ambiguous
Do not ask for target selection when the user already chose a target such as Docker Compose, Kubernetes, Azure Container Apps, Azure App Service, Azure Kubernetes Service (AKS), or AWS. Use the chosen target and continue with its reference.
If the user did not explicitly choose a deployment target and the AppHost does not already contain exactly one deployment environment, ask where they want to deploy before adding integrations, editing the AppHost, publishing artifacts, or deploying. Use a single multiple-choice question:
Where do you want to deploy this Aspire app?
Show these choices:
| Choice | Aspire add command | Use when |
|---|---|---|
| Docker Compose | aspire add docker | The user wants local/server container deployment artifacts for Docker or Podman. |
| Kubernetes | aspire add kubernetes | The user has an existing Kubernetes cluster and wants Helm/Kubernetes artifacts or direct cluster deployment. |
| Azure Container Apps | aspire add azure-appcontainers | The user wants an Azure-managed container platform for distributed apps and services. |
| Azure App Service | aspire add azure-appservice | The user wants Azure website hosting for web apps/APIs that fit the App Service model. |
| Azure Kubernetes Service (AKS) | aspire add azure-kubernetes | The user wants Aspire to provision and deploy to Azure-managed Kubernetes. |
| AWS | aspire add aws | The user wants Aspire to publish/deploy through the AWS Aspire integrations and AWS CDK. |
If the user says only "Azure", ask again with just the Azure choices: Azure Container Apps, Azure App Service, or Azure Kubernetes Service (AKS). If the AppHost already contains exactly one deployment environment and the user did not ask to change targets, use that target and tell the user what was detected.
Ask before creating cloud resources when intent is not explicit
Cloud deploys can create billable resources. If the user asked for a plan, preview, validation, or "make this deployable", stop after the deployment plan/artifacts and ask before running the command that provisions resources.
If the user explicitly asked to deploy now, continue through preflight and deployment, but still surface any target choice, subscription/resource group ambiguity, or missing parameter decisions before provisioning.
Keep Azure deployment Aspire-native
The Azure deployment path in this skill is aspire add <azure-target>, AppHost environment configuration, aspire publish, and aspire deploy. Do not route Azure deployment work through a separate Azure deployment tool or generated infrastructure workflow.
Default workflow
1. Orient to the Aspire workspace.
- Start with
aspire lsto list AppHosts in the current scope, then useaspire.config.json, AppHost project files, oraspire psif more context is needed. - If no AppHost exists, stop deployment work and invoke the
aspireifyskill to initialize/wire the AppHost before continuing. - Identify C# vs TypeScript AppHost.
- Prefer Aspire CLI commands for discovery and state inspection.
2. Clarify or infer the deployment target.
- If the user named Docker Compose, Kubernetes, Azure Container Apps, Azure App Service, Azure Kubernetes Service (AKS), or AWS, load that target reference without asking again.
- If they only said "deploy", inspect existing AppHost target environment resources.
- If exactly one target environment already exists, use it and state what was detected.
- If multiple targets exist, none exists, or the user says only "Azure", ask where to deploy using the choices above.
3. Load target and app-type references.
- Docker Compose: references/docker-compose.md
- Kubernetes and Azure Kubernetes Service (AKS): references/kubernetes.md
- Azure Container Apps/App Service/Azure Kubernetes Service (AKS): references/azure.md
- AWS: references/aws.md
- JavaScript app resources: references/javascript.md
- CI/CD or GitHub Actions automation: references/cicd.md
4. Use Aspire docs search for current guidance.
- Search and get the target deployment docs.
- Search API docs before editing AppHost code.
5. Apply the target code changes.
- Run the target's
aspire add ...command if the integration is missing. - Add the deployment environment resource to the AppHost.
- Do not add explicit compute-environment assignment for the common single-environment case. Only disambiguate when the AppHost has multiple deployment environments. In C# this is usually
WithComputeEnvironment(...); for TypeScript AppHosts, verify the current language-specific docs before assuming an equivalent. - Add only the target-specific customization APIs the deployment needs, such as endpoint exposure, Helm settings, Compose file customization, Azure site/container app customization, or AWS publish target overrides.
6. Preflight the deployment model.
- Confirm the target integration package exists in the AppHost.
- Confirm the AppHost has the target environment resource.
- Confirm compute resources are assigned to the target environment only when multiple compute environments exist. A single compute environment is the common case and can be inferred.
- Inventory parameters, secrets, connection strings, external endpoints, container registries, and target-specific prerequisites.
- For Azure or AWS, confirm auth, target account/subscription, region/location, and resource group/stack context.
7. Preview before applying.
- Run
aspire publish --list-stepsoraspire deploy --list-steps. - Use
aspire publish -o <scratch-or-output-path>when artifact review is requested. - Treat published artifacts as a preview/handoff.
aspire deployresolves values and applies the deployment from the AppHost model; it does not consume a previously published output directory. - Summarize resources, endpoints, parameters, secrets, identities, and generated artifacts.
8. Deploy or hand off.
- Run
aspire deploywhen the user asked to deploy and preflight is complete. - Run a named step with
aspire do <step>only when the user asked for a specific pipeline step. - For published artifacts, explain the target-native apply step.
9. Destroy only when explicitly requested.
- Run
aspire destroyto execute the selected AppHost/environment's target destroy pipeline. - Confirm the AppHost, environment, target account/subscription/cluster, and destructive intent before running it.
- Use
--yesonly when the user or CI workflow already made teardown intent explicit. - Prefer
aspire destroyover target-native delete commands unless you are troubleshooting failed teardown or cleaning up unmanaged leftovers.
10. Verify the outcome.
- Use target output,
aspire describe, cloud CLI, Docker Compose, kubectl, or endpoint checks appropriate to the target. - After destroy, verify target resources are removed or record any leftovers that require manual cleanup.
AppHost target detection
Search the AppHost for deployment environment resources:
| Target | Aspire add command | Integration | AppHost environment concept |
|---|---|---|---|
| Docker Compose | aspire add docker | Docker hosting | Docker Compose environment |
| Kubernetes | aspire add kubernetes | Kubernetes hosting | Kubernetes environment |
| Azure Container Apps | aspire add azure-appcontainers | Azure Container Apps hosting | Azure Container Apps environment |
| Azure App Service | aspire add azure-appservice | Azure App Service hosting | Azure App Service environment |
| Azure Kubernetes Service (AKS) | aspire add azure-kubernetes | Azure Kubernetes hosting | Azure Kubernetes Service (AKS) environment |
| AWS | aspire add aws | AWS hosting | AWS CDK environment |
Use this table only for orientation. Before editing code, verify the current API in Aspire docs for the AppHost language.
Parameter and secret preflight
Parameters are deployment inputs. They may be supplied by configuration files, user secrets, environment variables, command-line args, interactive prompts, or CI/CD secret stores depending on the target and command.
Before deployment, report:
- Parameter name from AppHost parameter APIs, including config-backed parameters
- Whether it is secret
- Expected provider syntax such as
Parameters__name; for parameter names with dashes, use underscores in environment variables, for exampleregistry-endpointbecomesParameters__registry_endpoint - Where it flows, such as a project environment variable, connection string, Key Vault secret, Helm Secret, Compose
.env, or Azure app setting - Whether a value appears configured or missing
Use aspire secret list for AppHost user secrets when appropriate, but do not print secret values. For deployment artifacts, inspect generated placeholders and mappings, not raw secret content.
Target references
- references/docker-compose.md - Docker Compose target, generated files, environment variables, cleanup.
- references/kubernetes.md - Kubernetes and Azure Kubernetes Service (AKS) target selection, Helm output, registry requirements, kubectl/Helm checks.
- references/azure.md - Azure target selection, Azure settings, Container Apps, App Service, and Azure Kubernetes Service (AKS).
- references/aws.md - AWS target selection, AWS CDK prerequisites, publish/deploy workflow, and AWS integration docs.
- references/javascript.md - JavaScript app deployment models, including Vite/static assets, Node/SSR servers, Next.js, and gateway/backend serving patterns.
- references/cicd.md - CI/CD and GitHub Actions workflow guidance for Aspire publish/deploy, parameters, secrets, registry auth, and cloud auth.
- references/preflight.md - Common preflight, preview, parameter, destroy, and validation checklist.
Agent execution
When running unattended (CI, scripted, agent-driven), append --non-interactive to every Aspire CLI invocation that may prompt — most importantly aspire publish, aspire deploy, and aspire destroy. For aspire destroy, also pass --yes only after the user has explicitly confirmed teardown intent (or a CI workflow already encodes that intent).
Prefer surfacing prompt-driving values up front (target subscription/region/resource group, parameters, secrets, registry credentials) so the unattended run does not stall. See references/preflight.md for the full preflight checklist.
Handoff Rules
| Scenario | Route To |
|---|---|
| Start, stop, wait, or restart the AppHost / its resources | aspire-orchestration skill |
| Logs, traces, metrics, dashboard for a running or deployed app | aspire-monitoring skill |
| AppHost authoring — adding integrations, wiring resources, environment setup | aspireify skill |
| Deployed-app diagnostics — App Insights, ACA logs, AKS Container Insights | azure-diagnostics skill (azure-skills) |
Never hand deployment off to azure-skills. Aspire handles publish, deploy, and destroy
end-to-end across Docker Compose / Kubernetes / Azure / AWS via the AppHost model.
Project-Local Skill Override
If .agents/skills/aspire-deployment/SKILL.md exists (dropped by aspire agent init), prefer it over this plugin skill — it is the authoritative project-local version with content version-aligned to the consumer's Aspire CLI. This plugin skill is the always-on safety net for repos that have not yet run aspire agent init.
name: aspire-deployment-eval
description: Evaluates the aspire-deployment skill for correct multi-target deployment guidance,
pipeline step handling, and ensuring no handoff to azure-skills for Aspire deployments.
version: "1.0"
type: capability
tags:
skill: aspire-deployment
config:
runs: 3
timeout: 120s
executor: copilot-sdk
model: gpt-5-mini
stimuli:
- name: deploy-destroy-001
prompt: I'm done with this preview deployment — how do I tear down everything Aspire provisioned?
tags:
priority: p1
area:
- core-flow
- aspire-13-3
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: uses_aspire_destroy
config:
prompt: Does the assistant's response recommend `aspire destroy` (new in Aspire 13.3) as the way to
tear down a deployed Aspire app? Answer based on intent.
- type: output-not-contains
config:
substring: az group delete
name: no_manual_teardown
- type: output-not-contains
config:
substring: kubectl delete
- type: output-not-contains
config:
substring: helm uninstall
- type: output-not-contains
config:
substring: docker compose down
- type: prompt
name: knows_destroy_is_cross_target
config:
prompt: The assistant's response should mention that `aspire destroy` is the inverse of `aspire
deploy` and works across deployment targets — Azure (resources deleted via Azure
Resource Manager), Kubernetes/AKS (Helm releases uninstalled, namespaces removed), and
Docker Compose (stacks stopped and removed). Bonus if it mentions the use case of CI
cleanup or ephemeral preview deployments.
- type: output-contains
config:
substring: aspire destroy
- type: output-not-contains
config:
substring: az group delete
- type: output-not-contains
config:
substring: kubectl delete
- type: output-not-contains
config:
substring: helm uninstall
- type: output-not-contains
config:
substring: docker compose down
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-azure-001
prompt: Deploy my Aspire application to Azure Container Apps
tags:
priority: p0
area: core-flow
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: uses_aspire_deploy
config:
prompt: Does the assistant's response recommend using 'aspire deploy' (or an equivalent Aspire CLI
deployment command) to deploy the application to Azure? Answer based on the intent, not
exact string matching.
- type: output-not-contains
config:
substring: azd up
name: no_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azd provision
- type: output-not-contains
config:
substring: azure-prepare
name: no_azure_skills
- type: output-not-contains
config:
substring: azure-deploy
- type: output-contains
config:
substring: aspire deploy
- type: output-not-contains
config:
substring: azd up
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azd init
- type: output-not-contains
config:
substring: azd provision
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-js-001
prompt: I want to publish my Next.js app via my Aspire AppHost — what's the recommended approach?
tags:
priority: p1
area:
- knowledge
- current-aspire
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: uses_addnextjsapp
config:
prompt: "Does the assistant's response recommend `AddNextJsApp(name, path)` as the first-class
Next.js helper? It should also note the requirement that `next.config.js` set `output:
\"standalone\"` so the build emits the standalone server, since `AddNextJsApp`
auto-configures Next.js standalone publishing."
- type: prompt
name: knows_publishas_family
config:
prompt: "Bonus: does the assistant's response mention or describe the broader current `PublishAs*`
family — `PublishAsStaticWebsite` (SPAs / Vite / Next.js export, preview),
`PublishAsNodeServer` (pre-bundled Node entry-points like SSR / TanStack Start /
SvelteKit), and `PublishAsPackageScript` (full Nitro Next.js, Remix, Astro SSR)? It does
NOT need to mention all three to pass — recognizing at least one alternative shows
awareness."
- type: output-contains
config:
substring: AddNextJsApp
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-multi-001
prompt: What deployment targets does Aspire support?
tags:
priority: p1
area:
- knowledge
- aspire-13-3
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: mentions_all_targets
config:
prompt: Does the assistant's response mention Azure as a deployment target for Aspire applications?
It should cover Azure Container Apps, Azure App Service, and Azure Kubernetes Service
(AKS). Answer based on the intent, not exact string matching.
- type: prompt
name: knows_k8s_helm_native
config:
prompt: The assistant's response should explain that in Aspire 13.3, Kubernetes deployment is native
and Helm-based — `aspire deploy` runs end-to-end after declaring an
`AddKubernetesEnvironment` (or `AddAzureKubernetesEnvironment` for AKS) and
`WithComputeEnvironment(...)`. It is acceptable (and correct) to note that the user
still needs cluster credentials (e.g., kubeconfig context, or `az aks get-credentials`).
- type: output-not-contains
config:
substring: kubectl apply
name: no_manual_k8s_tooling
- type: output-not-contains
config:
substring: helm install
- type: output-contains
config:
substring: Azure
- type: output-contains
config:
substring: Docker
- type: output-contains
config:
substring: Kubernetes
- type: output-not-contains
config:
substring: kubectl apply
- type: output-not-contains
config:
substring: helm install
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-step-001
prompt: I just need to re-seed the database, not redeploy everything
tags:
priority: p1
area: core-flow
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: uses_aspire_do
config:
prompt: Does the assistant's response recommend using 'aspire do' (or an equivalent Aspire CLI
command for running individual pipeline steps) rather than a full deployment? Answer
based on the intent, not exact string matching.
- type: prompt
name: not_full_deploy
config:
prompt: Does the assistant's response use 'aspire do seed-data' or a similar named-step command
rather than recommending a full 'aspire deploy' when the user only wants to re-run one
pipeline step? Answer based on intent.
- type: output-contains
config:
substring: aspire do
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-notool-001
prompt: What tools do I need to deploy my Aspire app to Azure?
tags:
priority: p0
area:
- safety-guardrail
- aspire-13-3
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: aspire_only
config:
prompt: The assistant's response should explain that Aspire handles Azure deployment natively via
'aspire deploy' — the AppHost IS the deployment plan. It's fine to mention that `az
login` (Azure credentials) is still needed.
- type: output-not-contains
config:
substring: azd up
name: no_external_tooling
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azd init
- type: output-not-contains
config:
substring: azd provision
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- type: output-not-contains
config:
substring: kubectl apply
- type: output-not-contains
config:
substring: helm install
- type: output-contains
config:
substring: aspire deploy
- type: output-not-contains
config:
substring: azd up
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azd init
- type: output-not-contains
config:
substring: azd provision
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: kubectl apply
- type: output-not-contains
config:
substring: helm install
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-list-steps-001
prompt: Before I deploy, I want to understand what steps the pipeline will run and if there are any
issues
tags:
priority: p1
area: core-flow
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
graders:
- type: prompt
name: uses_list_steps
config:
prompt: Does the assistant's response recommend using `aspire publish --list-steps` (or `aspire
deploy --list-steps`, or another `--list-steps`-style pipeline inspection) to preview
the deployment pipeline before actually deploying? It should suggest inspecting the
pipeline first rather than jumping straight to `aspire deploy`. Answer based on intent —
accept any phrasing that conveys previewing pipeline steps via the Aspire CLI's
list-steps flag.
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: deploy-publish-001
prompt: I just want to generate the deployment manifests without deploying
tags:
priority: p0
area: core-flow
environment:
files:
- src: ../../../evals/csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
dest: csharp-apphost/MyApp.AppHost/MyApp.AppHost.csproj
- src: ../../../evals/csharp-apphost/MyApp.AppHost/Program.cs
dest: csharp-apphost/MyApp.AppHost/Program.cs
- src: ../../../evals/csharp-apphost/aspire.config.json
dest: csharp-apphost/aspire.config.json
graders:
- type: prompt
name: uses_publish
config:
prompt: Does the assistant's response recommend using 'aspire publish' (or an equivalent Aspire CLI
artifact generation command) to generate deployment manifests without deploying? Answer
based on the intent, not exact string matching.
- type: prompt
name: distinguishes_publish_deploy
config:
prompt: The assistant's response should clearly distinguish between 'aspire publish' (artifact
generation only) and 'aspire deploy' (full pipeline including deployment). It should use
'aspire publish' since the user only wants artifacts.
- type: output-contains
config:
substring: aspire publish
- type: output-not-contains
config:
substring: azd up
name: never_azd
- type: output-not-contains
config:
substring: azd deploy
- type: output-not-contains
config:
substring: azure-prepare
- type: output-not-contains
config:
substring: azure-deploy
- name: should_trigger_01
description: "Reason: Direct deployment request — matches 'deploy to Azure' keyword"
prompt: Deploy my Aspire app to Azure
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_02
description: "Reason: Direct CLI invocation of aspire publish"
prompt: Run aspire publish to generate deployment artifacts
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_03
description: "Reason: Named pipeline step — aspire do is deployment"
prompt: Run the seed-data pipeline step with aspire do
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_04
description: "Reason: K8s artifact generation routes to aspire-deployment"
prompt: Generate deployment artifacts for Kubernetes with Aspire
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_05
description: "Reason: Deployment troubleshooting routes to aspire-deployment"
prompt: My aspire deploy is stuck — how do I unstick or reset the deployment?
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_06
description: "Reason: Docker Compose is an Aspire deploy target"
prompt: Push my Aspire app to a Docker Compose target
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_07
description: "Reason: aspire destroy is deployment lifecycle"
prompt: Tear down my Aspire deployment
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_08
description: "Reason: Direct aspire destroy invocation"
prompt: Run aspire destroy to remove my preview environment
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_09
description: "Reason: AddNextJsApp + publish is deployment"
prompt: Publish my Next.js app via Aspire with AddNextJsApp
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_10
description: "Reason: AKS is an Aspire deploy target via AddAzureKubernetesEnvironment"
prompt: Deploy my Aspire app to AKS
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_11
description: "Reason: AWS is an Aspire deploy target via `aspire add aws` + CDK environment"
prompt: Deploy my Aspire app to AWS
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_12
description: "Reason: Preflight / preview workflow is owned by aspire-deployment"
prompt: Validate my Aspire deployment plan before applying
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_trigger_13
description: "Reason: --list-steps is the canonical pipeline preview in aspire-deployment"
prompt: Inspect the deployment pipeline steps with aspire publish --list-steps
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: invokes_aspire_deployment
config:
required:
- aspire-deployment
- name: should_not_trigger_01
description: "Reason: Local start routes to aspire-orchestration"
prompt: Start my Aspire app locally
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_02
description: "Reason: Logs route to aspire-monitoring"
prompt: Show me the application logs
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_03
description: "Reason: Resource wait routes to aspire-orchestration"
prompt: Wait for the database to be ready
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_04
description: "Reason: Deployed monitoring routes to azure-diagnostics"
prompt: Check my App Insights dashboard
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_05
description: "Reason: Non-Aspire Azure work"
prompt: Create an Azure VM
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_06
description: "Reason: Not deployment related"
prompt: Run my unit tests
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_07
description: "Reason: AppHost wiring routes to aspireify"
prompt: Wire up my AppHost with Postgres and Redis
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
- name: should_not_trigger_08
description: "Reason: Traces route to aspire-monitoring"
prompt: Show me the OpenTelemetry traces
tags:
priority: p1
area: routing
graders:
- type: skill-invocation
name: does_not_invoke_aspire_deployment
config:
disallowed:
- aspire-deployment
AWS deployment
Use this reference when the user asks to deploy an Aspire app to AWS or to generate AWS CDK/CloudFormation deployment artifacts.
AWS deployment is currently a preview path driven by the AWS Aspire integrations. Treat the AWS repository as the source of truth, verify the installed package/API shape before editing, and do not invent TypeScript deployment APIs. AWS deployment has no TypeScript AppHost support yet.
Source of truth and docs lookup
Use the AWS Aspire integrations repository for AWS-specific deployment guidance:
https://github.com/aws/integrations-on-dotnet-aspire-for-aws
Use these repository docs when available:
README.mdfor the deployment overview and prerequisites.src/Aspire.Hosting.AWS/README.mdfor package-level setup.docs/deployment-design.mdfor publish target overrides, CDK constructs, and advanced customization.
Do not use aspire docs search for AWS deployment guidance. The AWS deployment docs are not in the Aspire docs index; use the AWS repository and deployment design document instead.
Target setup
Add the AWS integration with:
aspire add awsThen configure the C# AppHost with an AWS CDK environment using the API shape supported by the installed integration. Current documented setup uses an AWS CDK environment, a preview defaults provider, and preview publisher APIs. Expect preview diagnostics such as ASPIREAWSPUBLISHERS001; follow the AWS repository guidance for the required suppressions instead of hiding warnings broadly.
Code changes to make
Make these changes in the C# AppHost when the AWS integration docs still show the C#-only preview API:
1. Run aspire add aws if the AppHost does not already reference Aspire.Hosting.AWS. 2. Add the AWS CDK environment near the top of the AppHost, before resources that should deploy:
#pragma warning disable ASPIREAWSPUBLISHERS001
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAWSCDKEnvironment(
name: "<stack-name>",
cdkDefaultsProviderFactory: CDKDefaultsProviderFactory.Preview_V1);3. Keep existing Aspire resources in the AppHost. Default AWS deployment mapping handles common resources without per-resource publish calls. 4. Keep WithReference(...) relationships between resources. The AWS deployment system uses references for environment variables, VPC attachment, and security group connectivity where supported. 5. Add AWS-specific resources only when the app actually needs them and the AWS docs show the current shape, such as AddAWSLambdaFunction for Lambda projects/handlers. 6. Add publish override methods only when the user asks for a specific AWS shape or the default mapping is wrong. For example, use an ECS Fargate/ALB publish target only after verifying the current method name in the AWS deployment design document. 7. Do not invent a TypeScript AWS deployment environment. If the AppHost is TypeScript, stop and report that the current AWS deployment integration is C# AppHost-focused.
Do not add AWS CDK constructs directly as the first approach. Start with Aspire resources and references, then use AWS construct callbacks or custom CDK stacks only for explicit infrastructure customization.
Prerequisites
Check:
- AWS credentials are available for the target account.
- The AWS region is known and matches the user's intended deployment target.
- Node.js 22.x is installed when the AWS CDK tooling requires it.
- AWS CDK is installed and available.
- The target account and region are bootstrapped for CDK before first deployment:
cdk bootstrap aws://<account-id>/<region>- Docker is available when compute resource images need to be built.
- Required AppHost parameters are configured or can be prompted.
- If the AppHost project references unsigned AWS CDK packages and the build reports package signing diagnostics, follow the AWS repository guidance for the narrow project warning suppression.
Use AWS CLI to verify identity and region before deploying:
aws sts get-caller-identity
aws configure list
aws configure get region
cdk --versionDo not print access keys, secret keys, session tokens, or resolved secret parameter values.
Preview and publish
Use Aspire publish to generate deployment artifacts before applying them when the user wants review or validation:
aspire publish --list-steps
aspire publish -o aws-artifactsFor AWS CDK deployment, the AWS integration transforms Aspire resources into CDK constructs and synthesizes CloudFormation templates under cdk.out in the output location. Inspect the generated CDK output before deploying when the user asked for a preview:
find aws-artifacts -maxdepth 3 -type f | sort
cdk ls --app aws-artifacts/cdk.out
cdk diff --app aws-artifacts/cdk.outThe exact output path can vary with the installed integration; inspect the publish output and generated files instead of assuming a fixed directory layout.
Deploy
Deploy with:
aspire deployThe AWS integration runs the publish step and then uses AWS CDK deployment against the configured AWS account and region.
Use aspire deploy --list-steps before applying changes when the user asked for validation or when the AppHost has custom AWS publish targets.
Destroy
Use Aspire to run the AWS target's destroy pipeline:
aspire destroy --environment <name>For AWS, aspire destroy delegates to the AWS deployment target for the selected AppHost/environment. Confirm the AWS account, region, CDK stack name, AppHost, and environment before running destroy. Use --yes only after destructive intent is explicit. Use AWS CLI or CDK destroy commands only to investigate failed teardown or clean up resources that the Aspire AWS target did not manage.
Resource mapping and customization
Current AWS guidance says resources are mapped to AWS services by default and can be overridden with publish extension methods. Keep these rules in mind:
- Web projects can map to ECS Fargate-style targets by default.
- Lambda project resources can map to AWS Lambda.
- Redis can map to ElastiCache.
WithReference()drives connectivity such as environment variables, VPC attachment, and security groups.- Custom CDK stacks and construct callbacks are advanced customization points; use them only when the user asks for infrastructure customization and verify the exact API in the AWS design document.
Do not assume every Aspire resource has an AWS publish target. If a resource has no supported mapping, call that out before deployment rather than implying it will be provisioned.
Troubleshooting live AWS state
Use AWS CLI to inspect live resources that Aspire deployed through CDK/CloudFormation:
aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE UPDATE_ROLLBACK_COMPLETE
aws cloudformation describe-stacks --stack-name "<stack-name>"
aws cloudformation describe-stack-events --stack-name "<stack-name>" --max-items 20
aws cloudformation list-stack-resources --stack-name "<stack-name>"Use service-specific commands based on the resources in the generated CDK output:
# ECS/Fargate
aws ecs list-clusters
aws ecs list-services --cluster "<cluster-name>"
aws ecs describe-services --cluster "<cluster-name>" --services "<service-name>"
# Lambda
aws lambda list-functions
aws lambda get-function --function-name "<function-name>"
# ElastiCache
aws elasticache describe-cache-clusters --show-cache-node-infoWhen a deploy fails, inspect CloudFormation stack events first, then the specific service that failed. Match live stack/resource names back to the AWS CDK environment name, Aspire deployment output, and generated cdk.out templates.
Common checks
- Confirm the generated AWS stack name and region before deployment.
- Confirm credentials match the intended account.
- Confirm CDK bootstrap has run for the account and region.
- Treat preview deployment APIs as subject to change; re-check the AWS repository before making assumptions.
- When customization is needed, use the AWS repository's deployment design document and verify the exact API for the AppHost language before editing.
- Confirm any AppHost parameters that become CloudFormation/CDK inputs, especially names containing punctuation, by inspecting the synthesized output.
- If an ECS service is unhealthy, inspect ECS service events, task status, logs, image pull permissions, and security groups.
- If CloudFormation rolls back, read the first failed stack event rather than only the final rollback event.
Azure deployment
Use this reference when the user asks to deploy an Aspire app to Azure, Azure Container Apps, Azure App Service, or Azure Kubernetes Service (AKS).
Use Aspire-native Azure deployment
For Aspire apps, start from the AppHost deployment model. Azure deployment should go through the Azure hosting integrations, AppHost environment resources, aspire publish, and aspire deploy.
Do not generate or hand-edit Azure infrastructure as the source of truth unless the user explicitly wants a published artifact handoff. The AppHost Azure environment determines what gets provisioned.
Choose Azure target
| Target | Aspire add command | Best fit | Integration | Environment concept |
|---|---|---|---|---|
| Azure Container Apps | aspire add azure-appcontainers | Distributed/containerized services with internal/external ingress | Azure Container Apps hosting | Azure Container Apps environment |
| Azure App Service | aspire add azure-appservice | Public web apps/APIs that fit the App Service website model | Azure App Service hosting | Azure App Service environment |
| Azure Kubernetes Service (AKS) | aspire add azure-kubernetes | Kubernetes workloads where Aspire should provision Azure Kubernetes infrastructure | Azure Kubernetes hosting | Azure Kubernetes Service (AKS) environment |
If the user only says "Azure", ask which target unless the AppHost already contains exactly one Azure environment resource or the scenario strongly implies one.
Use these choices:
| Choice | Aspire add command | Use when |
|---|---|---|
| Azure Container Apps | aspire add azure-appcontainers | The user wants an Azure-managed container platform for distributed apps and services. |
| Azure App Service | aspire add azure-appservice | The user wants Azure website hosting for web apps/APIs that fit the App Service model. |
| Azure Kubernetes Service (AKS) | aspire add azure-kubernetes | The user wants Aspire to provision and deploy to Azure-managed Kubernetes. |
Docs to load
Always start with current docs:
aspire docs search "Azure Container Apps deployment"
aspire docs search "Azure App Service deployment"
aspire docs search "Azure Kubernetes Service deployment"
aspire docs search "Azure Kubernetes Service hosting integration"
aspire docs get "deploy-to-azure-container-apps"
aspire docs get "configure-azure-container-apps-environments"
aspire docs get "deploy-to-azure-app-service"
aspire docs get "set-up-azure-app-service-in-the-apphost"
aspire docs get "deploy-to-azure-kubernetes-service-aks"
aspire docs get "external-parameters"Some Azure deployment searches can return noisy integration results. Search first so you can find renamed pages, then prefer the known deployment slugs above when they are available. If one of these known slugs is not available in the installed Aspire docs, inspect the closest current replacement before editing.
Use API docs before editing. Search for the target environment, endpoint, and customization concepts in the AppHost language you detected:
aspire docs api search "AddAzureContainerAppEnvironment" --language csharp
aspire docs api search "AddAzureContainerAppEnvironment" --language typescript
aspire docs api search "AddAzureAppServiceEnvironment" --language csharp
aspire docs api search "AddAzureAppServiceEnvironment" --language typescript
aspire docs api search "AddAzureKubernetesEnvironment" --language csharp
aspire docs api search "AddAzureKubernetesEnvironment" --language typescript
aspire docs api search "WithExternalHttpEndpoints" --language csharp
aspire docs api search "WithExternalHttpEndpoints" --language typescriptShared Azure preflight
Check:
- Azure CLI is installed when local deploy uses Azure CLI credentials.
- The user is authenticated (
az login) or anotherAzure:CredentialSourceis configured. - Target subscription, location, and resource group are known.
- Required AppHost parameters are configured or can be prompted.
- The AppHost has the correct Azure target integration and environment resource.
- Production-only resources are not hidden behind run-mode-only execution context checks.
- Compute resources are assigned to the intended Azure environment when multiple compute environments exist.
Azure deployment settings:
| Setting | Environment variable | Purpose |
|---|---|---|
Azure:SubscriptionId | Azure__SubscriptionId | Target subscription |
Azure:Location | Azure__Location | Azure region |
Azure:ResourceGroup | Azure__ResourceGroup | Resource group |
Azure:CredentialSource | Azure__CredentialSource | Credential source override |
For local development, aspire secret set can store these values for the AppHost:
aspire secret set "Azure:SubscriptionId" "<subscription-id>"
aspire secret set "Azure:Location" "<region>"
aspire secret set "Azure:ResourceGroup" "<resource-group>"Do not use aspire secret set as the deployment parameter mechanism. It is a local/dev convenience today. For publish/deploy, TypeScript AppHosts, CI, and other non-interactive deploys, set deployment settings and AppHost parameters as environment variables on the aspire deploy process:
Azure__SubscriptionId="<subscription-id>" \
Azure__Location="westus2" \
Azure__ResourceGroup="my-app-rg" \
Parameters__api_key="<secret-value>" \
aspire deploy --apphost ./apphost.ts --environment Production --non-interactiveDo not print secret values. Subscription/resource group/location are not secrets, but still summarize them carefully.
If a parameter name contains -, use _ in the environment variable name. For example, AppHost parameter registry-endpoint maps to Parameters__registry_endpoint.
If az account show reports a tenant but aspire deploy later prompts during fetch-tenant, do not assume aspire secret set "Azure:TenantId" ... will answer that prompt. Tenant selection can still be a pipeline prompt. Run the deploy in a real interactive terminal/PTY, or make the Azure CLI login context unambiguous before deploying, for example with az login --tenant <tenant-id> or azure/login's tenant-id input in GitHub Actions.
Azure Container Apps
Setup:
aspire add azure-appcontainersCode changes:
1. Add an Azure Container Apps environment resource.
C# AppHost shape:
var aca = builder.AddAzureContainerAppEnvironment("aca");TypeScript AppHost shape:
const aca = await builder.addAzureContainerAppEnvironment("aca");2. Add .WithExternalHttpEndpoints() to C# compute resources that should be publicly reachable, such as projects, JavaScript/Python executables, containers, Dockerfiles, and similar workloads. For TypeScript AppHosts, use the endpoint/external endpoint API returned by docs. 3. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each Azure Container Apps workload; in C#, add .WithComputeEnvironment(aca) to each compute resource that should deploy there. For TypeScript AppHosts, verify the current language-specific docs before assuming an equivalent assignment API. 4. Do not add PublishAsAzureContainerApp(...) / publishAsAzureContainerApp(...) for a default Container App deployment. Add it only when the user needs per-resource Container App customization. Use Container App Job APIs only for worker/job resources that should run as jobs. 5. Add managed Azure resources for production dependencies when appropriate, then keep normal WithReference / withReference connections so Aspire wires app settings, identities, and connection details.
Key checks:
- One external HTTP/HTTP2 target-port group becomes the main ingress.
- Multiple external endpoint groups are not supported.
- External non-HTTP endpoints are not supported.
- HTTP/HTTP2 and TCP endpoints cannot be mixed on the same target port.
- The external HTTP endpoints API marks endpoints reachable outside the Container Apps environment; verify the exact API name for C# or TypeScript before editing.
- Internal services should not be made external unless the user wants public access.
- HTTP endpoints are upgraded to HTTPS by default for deployed endpoint URLs; only disable the upgrade when the user explicitly wants HTTP.
- Volumes and bind mounts become Azure Files-backed mounts, with generated storage accounts, file shares, and managed environment storage.
- Aspire provisions or attaches ACR, builds images, pushes images, and grants pull permissions with managed identity.
- The Aspire dashboard is included by default unless the environment disables it.
Use the per-resource Container Apps customization API only when customization is required, and verify the exact API name for the AppHost language.
Azure App Service
Setup:
aspire add azure-appserviceCode changes:
1. Add an Azure App Service environment resource.
C# AppHost shape:
var appService = builder.AddAzureAppServiceEnvironment("appservice");TypeScript AppHost shape:
const appService = await builder.addAzureAppServiceEnvironment("appservice");2. Add .WithExternalHttpEndpoints() to the C# web-facing compute resources that should become websites, such as projects, JavaScript/Python executables, containers, Dockerfiles, and similar workloads. For TypeScript AppHosts, use the endpoint/external endpoint API returned by docs. 3. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each App Service workload; in C#, add .WithComputeEnvironment(appService) to each website compute resource that should deploy there. 4. Keep background workers, infrastructure containers, and internal-only services out of App Service unless the docs say the resource is supported. Move dependencies to managed Azure resources or choose Container Apps/Azure Kubernetes Service (AKS). 5. Do not add PublishAsAzureAppServiceWebsite(...) / publishAsAzureAppServiceWebsite(...) for a default website deployment. Add it only when the user needs website customization such as app settings, deployment slots, tags, or infrastructure callbacks. 6. Use SkipEnvironmentVariableNameChecks() only when the user intentionally accepts App Service's dashed-setting behavior and the app does not depend on the original dashed key at runtime.
Key checks:
- App Service is a public website model.
- Supported workloads are web-facing project resources and Dockerfile-backed web containers.
- External HTTP/HTTPS endpoints are required for deployed websites.
- Only HTTP/HTTPS endpoints are supported.
- App Service supports a single target port for a deployed website. Multi-port public apps do not fit this target.
- Internal-only endpoints and arbitrary infrastructure containers do not fit this target.
- App Service upgrades external HTTP endpoint URLs to HTTPS by default.
- The environment creates an App Service Plan with default SKU
P0V3/Premium Linux, a container registry, managed identity, and the dashboard by default. - Application Insights is optional and must be enabled/configured intentionally.
- Environment variable names containing
-fail validation because App Service removes dashes at runtime; prefer dash-free connection names rather than bypassing validation. - Use managed Azure resources for databases, caches, and brokers.
Use the per-site App Service customization API only for app settings, deployment slots, tags, validation overrides, or other per-site changes, and verify the exact API name for the AppHost language.
Azure Kubernetes Service (AKS)
Setup:
aspire add azure-kubernetesCode changes:
1. Add an Azure Kubernetes Service (AKS) environment resource.
C# AppHost shape:
var aks = builder.AddAzureKubernetesEnvironment("aks");TypeScript AppHost shape:
const aks = await builder.addAzureKubernetesEnvironment("aks");2. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each Azure Kubernetes Service (AKS) workload; in C#, add .WithComputeEnvironment(aks) to each compute resource that should deploy there, such as projects, JavaScript/Python executables, containers, Dockerfiles, and similar workloads. 3. Do not add a separate plain Kubernetes environment for the same Azure Kubernetes Service (AKS) target. The Azure Kubernetes environment owns the Kubernetes/Helm deployment path. 4. Use Azure Kubernetes Service (AKS) customization APIs only when needed, such as node pools, system node pool SKU/count, subnet integration, workload identity, custom ACR, or Application Gateway for Containers. 5. Use Kubernetes Gateway/Ingress/service customization APIs for public exposure. Do not assume adding the environment makes every workload public.
For Azure Kubernetes Service (AKS) details, also load kubernetes.md.
Azure Kubernetes Service (AKS) uses the Azure Kubernetes integration to provision Azure Kubernetes Service (AKS) infrastructure and then deploys through an inner Kubernetes/Helm environment. It auto-creates ACR by default, supports explicit ACR replacement, and can customize node pools, subnets, workload identity, and Application Gateway for Containers. Verify exact APIs before editing.
Preview and deploy
List pipeline steps:
aspire publish --list-steps
aspire deploy --list-stepsGenerate artifacts without applying:
aspire publish -o azure-artifactsDeploy:
aspire deployFor local Azure deploys, prefer a real interactive terminal for the first apply. Azure deployment can prompt for values that are not AppHost parameters, such as tenant selection when multiple tenants are available. Use --non-interactive only after configuring deploy-time values with environment variables and confirming the Azure CLI login context is unambiguous.
Do not pipe an interactive aspire deploy through tee, tail, or another command when prompts may appear. The pipe can make the current terminal non-interactive and selection prompts will fail. Use the attached terminal output and the Aspire CLI log path printed by the command instead of capturing the transcript with a pipe.
Use --environment <name> for staging/production context:
aspire deploy --environment stagingPublished Azure artifacts are for preview or handoff. aspire deploy resolves parameters and applies the Azure deployment from the AppHost model.
Destroy
Use Aspire to run the Azure target's destroy pipeline:
aspire destroy --environment <name>For Azure, aspire destroy delegates to the Azure deployment target for the selected AppHost/environment. Confirm the Azure subscription, resource group, environment name, and AppHost before running destroy. Use --yes only after the user has explicitly approved teardown or in an environment-protected cleanup workflow. Use Azure CLI after destroy to verify resource removal or investigate leftovers; do not start with az group delete or target-specific delete commands for resources managed by the Aspire Azure target unless aspire destroy cannot complete.
Common troubleshooting
Use Azure CLI to inspect live Azure state that Aspire deployed, while keeping deployment changes in the AppHost and aspire deploy.
Start by confirming the active subscription and resource group:
az account show --query "{name:name, id:id, tenantId:tenantId}" --output table
az group show --name "<resource-group>" --query "{name:name, location:location, provisioningState:properties.provisioningState}" --output table
az deployment group list --resource-group "<resource-group>" --query "[].{name:name, state:properties.provisioningState, timestamp:properties.timestamp}" --output table
az resource list --resource-group "<resource-group>" --query "[].{name:name, type:type, location:location}" --output tableUse target-specific inspection commands:
# Azure Container Apps
az containerapp list --resource-group "<resource-group>" --query "[].{name:name, state:properties.runningStatus, fqdn:properties.configuration.ingress.fqdn}" --output table
az containerapp revision list --resource-group "<resource-group>" --name "<container-app-name>" --query "[].{name:name, active:properties.active, healthState:properties.healthState}" --output table
az containerapp logs show --resource-group "<resource-group>" --name "<container-app-name>" --tail 100
# Azure App Service
az webapp list --resource-group "<resource-group>" --query "[].{name:name, state:state, hostNames:defaultHostName}" --output table
az webapp config appsettings list --resource-group "<resource-group>" --name "<web-app-name>" --query "[].name" --output table
az webapp log tail --resource-group "<resource-group>" --name "<web-app-name>"
# Azure Kubernetes Service (AKS)
az aks show --resource-group "<resource-group>" --name "<cluster-name>" --query "{name:name, state:provisioningState, fqdn:fqdn, kubernetesVersion:kubernetesVersion}" --output table
az aks get-credentials --resource-group "<resource-group>" --name "<cluster-name>"
kubectl get pods,svc,ingress --all-namespaces
helm list --all-namespacesWhen troubleshooting generated Azure resources, match the live resource names and tags back to the Aspire deployment summary, AppHost environment resource name, and selected --environment value. Do not print secret values; for Key Vault or app settings, inspect key names and references rather than values.
- Missing Azure settings: configure
Azure__SubscriptionId,Azure__Location, and optionallyAzure__ResourceGroupon the deploy process. - Wrong subscription: check
az account showand compare toAzure__SubscriptionIdor AppHost config. - Failed resource group deployment: inspect the failed deployment with
az deployment group show --resource-group "<resource-group>" --name "<deployment-name>"and then inspect operation errors withaz deployment operation group list --resource-group "<resource-group>" --name "<deployment-name>" --query "[?properties.provisioningState=='Failed']". - Parameter prompts in CI: provide
Parameters__*environment variables through pipeline secrets/variables. - Secrets to Key Vault: use the Azure Key Vault hosting integration and secret APIs only after confirming docs and user intent.
- Public endpoint surprise: inspect external endpoint configuration and target endpoint rules before deployment.
- Container Apps revision unhealthy: check revision health, ingress, image pull, managed identity, and logs with
az containerapp revision listandaz containerapp logs show. - App Service unsupported resource: move backing services to managed Azure resources or choose Container Apps/Azure Kubernetes Service (AKS) instead.
- App Service dashed setting failure: rename the connection/environment key if possible; bypass validation only when the app does not depend on the original dashed key at runtime.
- Azure Kubernetes Service (AKS) workload not reachable: refresh credentials with
az aks get-credentials, then inspect pods, services, ingress/gateway resources, and Helm release status withkubectlandhelm.
CI/CD and GitHub Actions deployment
Use this reference when the user asks to automate Aspire publish/deploy in CI/CD, create a GitHub Actions workflow, publish release artifacts, push container images, or run deployment validation in a pipeline.
CI/CD should still start from the AppHost model. The pipeline should install the Aspire CLI, install the AppHost/resource toolchains needed by the repo, restore/build the workspace, provide AppHost parameters through CI secrets/variables, run Aspire publish/deploy/list-step commands, and then either upload generated artifacts or deploy with the target's credentials.
Docs to load
Use these searches and docs:
aspire docs search "ci"
aspire docs search "github actions"
aspire docs search "external parameters deployment"
aspire docs get "testing-in-cicd-pipelines"
aspire docs get "example-app-lifecycle-workflow"
aspire docs get "external-parameters"testing-in-cicd-pipelines is primarily about tests, but it includes useful CI facts: Linux runners have Docker available, CI needs explicit timeouts for tests, Azure credentials must be configured explicitly, and secrets should come from CI variables. example-app-lifecycle-workflow is a worked GitHub Actions example for publishing Aspire artifacts and pushing images.
Decide publish, deploy, or handoff
Ask which CI/CD outcome the user wants if it is not clear:
| Outcome | Use when | Typical command |
|---|---|---|
| Validate deployment model | PR or pre-merge check should prove the AppHost can produce deployment steps/artifacts | aspire publish --list-steps or aspire deploy --list-steps |
| Publish artifacts | CI should produce Compose/Helm/CDK/Bicep or other target artifacts for review or later apply | aspire publish -o <output> |
| Push images only | CI should build/push project images but not deploy infrastructure | aspire do <push-step> after checking aspire deploy --list-steps |
| Deploy from CI | Protected branch/environment should provision/update target infrastructure | aspire deploy --environment <name> |
| Destroy from CI | Explicit cleanup workflow should tear down an Aspire-owned deployment | aspire destroy --environment <name> --yes |
Do not assume aspire deploy consumes a previous aspire publish output. aspire deploy applies directly from the AppHost model and resolves values for the selected environment.
GitHub Actions workflow shape
Use this baseline shape, then add the setup block that matches the AppHost/resource graph and layer target-specific auth and parameters on top:
name: Deploy
on:
workflow_dispatch:
push:
branches: [main]
permissions:
contents: read
packages: write
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Install Aspire CLI
run: |
curl -sSL https://aspire.dev/install.sh | bash
echo "$HOME/.aspire/bin" >> "$GITHUB_PATH"
- name: Inspect Aspire deployment steps
run: |
aspire ls
aspire publish --list-steps
aspire deploy --list-stepsAdd one or both setup blocks before Aspire commands:
| AppHost/resources | Setup guidance |
|---|---|
| C# AppHost or .NET project resources | Install .NET with actions/setup-dotnet, then use the repo's restore/build command. |
| TypeScript AppHost or JavaScript resources | Install Node with actions/setup-node, then run the repo's package-manager install/build commands. |
| Mixed C#/TypeScript graph | Use both setup blocks so the AppHost and all compute resources can be restored, built, and published. |
C# AppHost setup:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Restore and build .NET workspace
run: |
dotnet restore
dotnet build --no-restoreTypeScript AppHost setup:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22.x
- name: Install and build TypeScript workspace
run: |
npm ci
npm run build --if-presentUse repository-specific setup instead of the generic snippets when the repo already has wrapper scripts, a local SDK restore step, a package manager other than npm, an AppHost package.json in a subdirectory, or a required build command.
Parameters and secrets
Map AppHost parameters through workflow env: using Aspire configuration environment-variable conventions:
env:
Parameters__registry_endpoint: ghcr.io
Parameters__registry_repository: ${{ github.repository }}
Parameters__api_key: ${{ secrets.API_KEY }}Rules:
- AppHost parameter
namemaps toParameters__name. - Parameter names with dashes use underscores in environment variables, for example
registry-endpointbecomesParameters__registry_endpoint. - Secret parameters should come from GitHub Actions secrets or environment secrets.
- Do not print secret values. Prefer listing parameter names/status before deployment.
- Use GitHub Environments for production secrets and required reviewers when
aspire deployprovisions cloud resources.
Container registry auth
For GitHub Container Registry, authenticate before Aspire push/publish/deploy steps that build and push images:
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}Then provide registry parameters if the AppHost models them:
- name: Push images with Aspire
env:
Parameters__registry_endpoint: ghcr.io
Parameters__registry_repository: ${{ github.repository }}
run: aspire do <push-step>Get the exact push/build step from aspire deploy --list-steps or aspire publish --list-steps; do not hardcode push unless the target docs/listed steps show it.
Publish artifacts in GitHub Actions
Use publish when the pipeline should produce artifacts for review or later apply:
- name: Publish Aspire artifacts
env:
Parameters__registry_endpoint: ghcr.io
Parameters__registry_repository: ${{ github.repository }}
run: aspire publish -o ./aspire-output
- name: Upload Aspire artifacts
uses: actions/upload-artifact@v4
with:
name: aspire-output
path: ./aspire-outputTreat published output as potentially sensitive. Docker Compose .env.<environment>, Helm values/secrets, CDK output, and target-specific deployment state can include resolved parameter values or secret references. Upload only what the user intends to retain.
Deploy from GitHub Actions
Use deploy only when the workflow is intentionally allowed to modify infrastructure:
- name: Deploy with Aspire
env:
Parameters__registry_endpoint: ghcr.io
Parameters__registry_repository: ${{ github.repository }}
run: aspire deploy --environment production --non-interactiveAdd target-specific authentication before this step:
- Docker Compose: runner needs Docker/Podman and access to the target Docker host if deploying remotely.
- Kubernetes: configure
kubectlcontext and registry pull auth beforeaspire deploy. - Azure: authenticate Azure CLI or Azure SDK credentials before
aspire deploy; setAzure__SubscriptionId,Azure__Location, and optionallyAzure__ResourceGroup. - AWS: configure AWS credentials/region, install CDK prerequisites, and bootstrap the account/region before
aspire deploy.
Never route Azure deployment through a separate Azure deployment tool from this skill. Keep Azure deployment Aspire-native with aspire deploy, and use Azure CLI only for authentication and live state inspection.
Destroy from CI/CD
Use aspire destroy for teardown workflows that intentionally run the AppHost deployment target's destroy pipeline:
- name: Destroy with Aspire
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
Azure__SubscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Azure__Location: ${{ vars.AZURE_LOCATION }}
Azure__ResourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }}
run: aspire destroy --environment production --yes --non-interactiveKeep destroy jobs manually triggered or gated by a protected GitHub Environment. Reuse the same target authentication, AppHost path, environment, and parameter conventions as deploy. Do not put destroy into normal validation or deploy jobs unless the workflow owns temporary infrastructure and teardown is part of the tested lifecycle. If CI also created external infrastructure that is outside the Aspire deployment target, such as a temporary Kubernetes cluster or registry, clean that up in separate explicit provider-specific steps after the Aspire destroy step.
Azure GitHub Actions auth
Use the repository's preferred Azure auth pattern. For OIDC with azure/login, ensure the workflow has id-token: write and the cloud app/federated credential is configured:
- name: Azure login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}Then provide Aspire Azure settings:
env:
Azure__SubscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Azure__Location: ${{ vars.AZURE_LOCATION }}
Azure__ResourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }}If the workflow uses service-principal secrets instead of OIDC, set AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_CLIENT_SECRET as secrets for Azure SDK authentication. Do not echo these values.
Azure GitHub Actions deployment pattern
A real Azure Aspire deployment workflow can be as small as checkout, AppHost toolchain setup, Aspire CLI install, Azure login, and aspire deploy. Use these checked-in workflow references when the user wants GitHub Actions to deploy directly to Azure through Aspire and gate it with a GitHub Environment:
- C# AppHost: github-actions-azure-csharp.yml
- TypeScript AppHost: github-actions-azure-typescript.yml
The C# AppHost reference has this shape:
name: Aspire Deploy CI/CD
on:
push:
branches: [live]
permissions:
id-token: write
contents: read
jobs:
aspire_deploy:
runs-on: ubuntu-latest
name: Deploy with Aspire
environment:
name: production
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
steps:
- uses: actions/checkout@v4
with:
submodules: true
lfs: false
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
dotnet-quality: preview
- name: Install Aspire CLI
run: curl -sSL https://aspire.dev/install.sh | bash
- name: Add Aspire CLI to PATH
run: echo "$HOME/.aspire/bin" >> "$GITHUB_PATH"
- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy with Aspire
run: aspire deploy --apphost ./src/apphost.cs --environment Production --non-interactive
env:
Azure__SubscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Azure__Location: ${{ vars.AZURE_LOCATION || 'eastus' }}
Azure__ResourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }}
Parameters__admin_password: ${{ secrets.ADMIN_PASSWORD }}Create a GitHub Environment named production and store deployment values there so approvals, branch rules, environment variables, and environment secrets apply to the deployment job:
| GitHub Environment value | Example names |
|---|---|
| Variables | AZURE_LOCATION, AZURE_RESOURCE_GROUP, app build variables that are safe to expose |
| Secrets | AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID, AppHost parameter secrets such as ADMIN_PASSWORD |
Adapt the example instead of copying it blindly:
- Start from the external
.ymlreference that matches the AppHost language, then adjust paths, package manager commands, package-manager caching, target branch, and parameter names. - Use
--apphost <path>when the workflow should pin a specific AppHost, such as a single-fileapphost.cs,apphost.ts, or an AppHost project file. - For TypeScript AppHosts, replace the .NET setup with Node/package-manager setup, deploy with
--apphost <path-to-apphost.ts> --non-interactive, and provide deployment settings and AppHost parameters through the deploy step'senv:. - Keep
id-token: writefor Azure OIDC login. - Put non-secret deployment settings in GitHub Environment variables when possible, such as
AZURE_LOCATIONandAZURE_RESOURCE_GROUP. - Put secret AppHost parameters in GitHub Environment secrets and pass them as
Parameters__*. - Add app-specific build metadata only when the app consumes it. For example, Vite apps need a
VITE_prefix for values intended for client-side build-time exposure. - Add extra Azure settings only when the AppHost declares them, such as
Azure__PostgresLocationfor a custom PostgreSQL region. - Add a separate preflight step with
aspire lsandaspire deploy --list-stepswhen the workflow should show planned deployment steps before applying changes.
Validation and troubleshooting
Before applying changes:
aspire ls
aspire publish --list-steps
aspire deploy --list-stepsAfter deployment, use the target reference's validation commands:
- Docker Compose:
docker compose psagainst generated files or the target Compose project. - Kubernetes:
kubectl get pods,kubectl get svc, andhelm status. - Azure:
az account show,az resource list, target-specificaz containerapp,az webapp, oraz akscommands. - AWS:
aws cloudformation describe-stacks, stack events, and service-specific AWS CLI commands.
Common CI/CD failures:
- Missing parameter: add
Parameters__*env vars or GitHub Environment secrets. - Wrong registry path: compare
Parameters__registry_endpointandParameters__registry_repositoryto generated image names. - Docker unavailable: use
ubuntu-*GitHub-hosted runners for Linux containers or a configured self-hosted runner. - Cloud auth uses the wrong identity/subscription/account: print identity metadata only, not secrets.
- Publish output contains sensitive values: reduce uploaded paths or use environment-protected artifacts.
- Deployment step name changed: rerun
aspire deploy --list-stepsand updateaspire do <step>.
Docker Compose deployment
Use this reference when the user asks for Docker Compose deployment, local container deployment artifacts, or a non-cloud deployment package.
Docs to load
Always start with current docs:
aspire docs search "Docker Compose deployment"
aspire docs search "Docker hosting integration"
aspire docs search "Docker Compose environment variables"
aspire docs get "deploy-to-docker-compose"
aspire docs get "docker-integration"
aspire docs get "<slug>"Use API docs before editing. Search in the AppHost language you detected:
aspire docs api search "Docker Compose environment" --language csharp
aspire docs api search "Docker Compose environment" --language typescript
aspire docs api search "Docker Compose service customization" --language csharp
aspire docs api search "Docker Compose service customization" --language typescriptTarget setup
Expected package and AppHost environment:
aspire add dockerAdd a Docker Compose environment resource using the C# or TypeScript API shape returned by Aspire docs. When a Docker Compose environment exists, compatible resources are automatically included in generated Compose output. Use the per-resource Docker Compose customization API only for customization.
Code changes to make
Make these changes in the AppHost, not in the generated Compose output:
1. Run aspire add docker if the AppHost does not already reference the Docker hosting integration. 2. Add a Docker Compose environment resource.
C# AppHost shape:
var compose = builder.AddDockerComposeEnvironment("docker-compose");TypeScript AppHost shape:
const compose = await builder.addDockerComposeEnvironment("docker-compose");3. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each Docker Compose workload; in C#, add .WithComputeEnvironment(compose) to each compute resource that should land in Compose. 4. For TypeScript AppHosts, verify the current language-specific docs before assuming an equivalent assignment API. 5. Keep normal app model relationships such as WithReference, endpoints, parameters, and connection strings in the AppHost. They flow into Compose environment variables and service dependencies. 6. Use customization APIs only for real Compose customization:
- C#:
compose.ConfigureComposeFile(...),compose.ConfigureEnvFile(...), andresource.PublishAsDockerComposeService(...). - TypeScript:
compose.configureComposeFile(...),compose.configureEnvFile(...), andresource.publishAsDockerComposeService(...).
Do not hand-edit docker-compose.yaml as the durable fix unless the user explicitly wants to eject generated artifacts.
Preflight
Check:
- Docker or Podman is installed and running.
- Docker must be at least 28.0.0, and Podman must be at least 5.0.0 for current Aspire CLI environment checks.
- The AppHost has a Docker Compose environment resource.
- The repo does not rely on local bind mounts that will be invalid on the target Docker host.
- Parameters and secrets are represented as placeholders in
.envafteraspire publishand resolved in.env.<environment>after prepare/deploy. - Any fixed ports are intentional and do not conflict on the deployment host.
Use ASPIRE_CONTAINER_RUNTIME=docker or ASPIRE_CONTAINER_RUNTIME=podman only when the user needs to force a runtime.
Preview and publish
Generate artifacts without starting containers:
aspire publishExpected output includes:
aspire-output/docker-compose.yamlaspire-output/.env- resource Dockerfiles when needed
For environment-specific output and image build without running the whole deploy, use the target's prepare step if docs/list-steps show it:
aspire deploy --list-steps
aspire do prepare-docker-compose --environment stagingThe exact step name depends on the Docker Compose environment resource name. Use the step shown by aspire deploy --list-steps: for an environment resource named docker-compose, the prepare step is prepare-docker-compose; for one named compose, it is prepare-compose.
Deploy and destroy
Deploy:
aspire deployAspire generates Compose output, builds images, writes environment-specific .env files, and runs Compose.
Run the Docker Compose target's destroy pipeline only when requested:
aspire destroyFor Docker Compose, aspire destroy delegates to the Compose deployment target for the selected AppHost/environment. Use Docker or Compose commands after destroy only to verify cleanup or investigate leftover containers, networks, volumes, or generated files.
Common decisions
Publish-only vs deploy
Use aspire publish when the user wants files to review or hand to another deployment system. Use aspire deploy when they want Aspire to start the Compose deployment.
aspire publish writes docker-compose.yaml and .env with blank placeholders for captured values. Prepare/deploy writes .env.<environment> with resolved values. Do not expect aspire deploy to consume a previously published directory.
Customizing generated Compose
Use docs-backed APIs:
- The Compose file customization API for global Compose model changes.
- The environment file customization API for generated
.envchanges. - The per-resource Docker Compose service customization API for service-level changes.
Do not hand-edit generated docker-compose.yaml as the source of truth unless the user explicitly wants to eject the artifact.
Environment files and bind mounts
Generated .env values are intentionally separated from environment-specific .env.<environment> values:
.envis a publish-time placeholder file and preserves existing user values when possible..env.<environment>is written by prepare/deploy with resolved parameter, image, and bind-mount values.- Project images are represented through image placeholders such as
<RESOURCE>_IMAGEuntil prepare/deploy resolves them. - Bind mount source paths are replaced by
<RESOURCE>_BINDMOUNT_<index>placeholders because local paths often do not exist on another Docker host. - Docker socket mounts are left as the platform socket path instead of being placeholderized.
Treat .env.<environment> as potentially sensitive.
Compose project name
Aspire uses a generated Compose project name based on the environment resource name and, when available, the AppHost path hash. This prevents common collisions between different AppHosts using the same environment name.
Service host names
When a service needs another service's Compose host name, use the Docker Compose environment's host address expression API from docs. Do not hardcode generated service names unless the docs or artifact prove them.
name: Aspire Deploy CSharp
on:
workflow_dispatch:
push:
branches: [live]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy CSharp AppHost with Aspire
environment:
name: production
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: true
steps:
- name: Checkout
# actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- name: Setup .NET
# actions/setup-dotnet@v4
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9
with:
dotnet-version: 10.0.x
dotnet-quality: preview
- name: Install Aspire CLI
run: |
curl -sSL https://aspire.dev/install.sh | bash
echo "$HOME/.aspire/bin" >> "$GITHUB_PATH"
- name: Azure Login
# azure/login@v2
uses: azure/login@1384c340ab2dda50fed2bee3041d1d87018aa5e8
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy with Aspire
run: aspire deploy --apphost ./src/AppHost/AppHost.csproj --environment Production
env:
Azure__SubscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Azure__Location: ${{ vars.AZURE_LOCATION || 'eastus' }}
Azure__ResourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }}
Parameters__admin_password: ${{ secrets.ADMIN_PASSWORD }}
name: Aspire Deploy TypeScript
on:
workflow_dispatch:
push:
branches: [live]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy TypeScript AppHost with Aspire
environment:
name: production
steps:
- name: Checkout
# actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
- name: Setup Node
# actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 22.x
- name: Install and build workspace
run: |
npm ci
npm run build --if-present
- name: Install Aspire CLI
run: |
curl -sSL https://aspire.dev/install.sh | bash
echo "$HOME/.aspire/bin" >> "$GITHUB_PATH"
- name: Azure Login
# azure/login@v2
uses: azure/login@1384c340ab2dda50fed2bee3041d1d87018aa5e8
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy with Aspire
run: aspire deploy --apphost ./apphost.ts --environment Production --non-interactive
env:
Azure__SubscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Azure__Location: ${{ vars.AZURE_LOCATION || 'eastus' }}
Azure__ResourceGroup: ${{ vars.AZURE_RESOURCE_GROUP }}
Parameters__admin_password: ${{ secrets.ADMIN_PASSWORD }}
JavaScript app deployment
Use this reference whenever an Aspire deployment includes JavaScript app resources, such as Vite, React, Vue, Angular, Astro, Next.js, Nuxt, or plain Node.js apps.
JavaScript resources are not just another deployment target. They need an explicit production serving model before the target reference can be trusted. A Vite dev server that works during aspire run is often build-only during publish/deploy unless the AppHost says who serves the built files.
Integration to add
aspire add javascriptThis adds Aspire.Hosting.JavaScript, which provides AddJavaScriptApp, AddNodeApp, AddViteApp, AddNextJsApp, package-manager helpers, and JavaScript publish modes.
Docs to load
Always start with current docs:
aspire docs search "javascript deployment"
aspire docs get "deploy-javascript-apps"
aspire docs get "set-up-javascript-apps-in-the-apphost"Use API docs before editing. Search in the AppHost language you detected:
aspire docs api search "AddJavaScriptApp" --language csharp
aspire docs api search "AddJavaScriptApp" --language typescript
aspire docs api search "AddNodeApp" --language csharp
aspire docs api search "AddNodeApp" --language typescript
aspire docs api search "AddViteApp" --language csharp
aspire docs api search "AddViteApp" --language typescript
aspire docs api search "AddNextJsApp" --language csharp
aspire docs api search "AddNextJsApp" --language typescript
aspire docs api search "PublishAsStaticWebsite" --language csharp
aspire docs api search "PublishAsStaticWebsite" --language typescript
aspire docs api search "PublishAsNodeServer" --language csharp
aspire docs api search "PublishAsNodeServer" --language typescript
aspire docs api search "PublishAsPackageScript" --language csharp
aspire docs api search "PublishAsPackageScript" --language typescript
aspire docs api search "PublishWithContainerFiles" --language csharp
aspire docs api search "PublishWithContainerFiles" --language typescript
aspire docs api search "PublishWithStaticFiles" --language csharp
aspire docs api search "PublishWithStaticFiles" --language typescriptSetup
Use Aspire.Hosting.JavaScript for Aspire 13+ apps. Aspire.Hosting.NodeJs is the old package name; do not add it for new guidance unless the target repo is intentionally pinned to older Aspire.
Resource choice
Choose the AppHost resource based on what the JavaScript app is during local development:
| Resource | Use when | C# shape | TypeScript shape |
|---|---|---|---|
| JavaScript app | Generic package-script-driven app | AddJavaScriptApp(...) | addJavaScriptApp(...) |
| Node app | A Node process starts a specific script file | AddNodeApp(...) | addNodeApp(...) |
| Vite app | Vite-based browser app or framework dev server | AddViteApp(...) | addViteApp(...) |
| Next.js app | Next.js app using the dedicated helper | AddNextJsApp(...) | addNextJsApp(...) |
AddNextJsApp and JavaScript publish methods are experimental. In C# AppHosts, follow docs for the ASPIREJAVASCRIPT001 suppression instead of suppressing warnings broadly.
Production serving model
Choose the production entrypoint before deploying:
| Production shape | Use when | AppHost pattern |
|---|---|---|
| Static frontend served by a backend | The backend should serve built frontend files from wwwroot, static, or similar | Backend resource uses PublishWithContainerFiles(frontend, "<path>") |
| Static frontend served by a gateway/BFF | YARP or another proxy is the public entrypoint and serves the built frontend | Gateway uses PublishWithStaticFiles(frontend) |
| Static frontend served by the JavaScript resource | The frontend should deploy as its own static website/container | JavaScript resource uses PublishAsStaticWebsite(...) |
| SSR or Node.js server with built output | The framework emits a server entrypoint/artifact | JavaScript resource uses PublishAsNodeServer(...) |
| SSR or Node.js server started by package script | Runtime needs package manager scripts and runtime dependencies | JavaScript resource uses PublishAsPackageScript(...) |
| Next.js standalone app | Next.js is configured for standalone output | Use AddNextJsApp(...) |
Do not assume the Vite dev server is the production server. During publish/deploy, Vite resources usually build static files unless the AppHost selects a JavaScript publish mode.
Code changes to make
1. Run aspire add javascript if the AppHost does not already reference the JavaScript hosting integration. 2. Add the appropriate JavaScript resource.
C# AppHost examples:
var frontend = builder.AddViteApp("frontend", "./frontend");
var api = builder.AddNodeApp("api", "./api", "server.js")
.WithHttpEndpoint(env: "PORT");TypeScript AppHost examples:
const frontend = await builder.addViteApp("frontend", "./frontend");
const api = await builder
.addNodeApp("api", "./api", "server.js")
.withHttpEndpoint({ env: "PORT" });3. Configure package manager and scripts only when defaults are wrong:
- C#:
WithNpm(...),WithYarn(...),WithPnpm(...),WithBun(...),WithBuildScript(...),WithRunScript(...). - TypeScript:
withNpm(...),withYarn(...),withPnpm(...),withBun(...),withBuildScript(...),withRunScript(...).
4. Add a production serving model from the table above. This is required for build-only browser apps. 5. Add WithExternalHttpEndpoints() / withExternalHttpEndpoints() only to the resource that owns the public production HTTP surface, such as the backend, gateway, static website, Node server, or Next.js app. 6. Keep dev-only gateway/proxy wiring behind run-mode checks when it depends on a dev server URL. Production routing must be configured on the production-serving resource, not assumed from Vite dev proxy settings. 7. After choosing the production-serving resource, apply the target reference for Docker Compose, Kubernetes, Azure, or AWS.
Target-specific notes
- Docker Compose: JavaScript resources can publish as containers or static-file-carrying build resources. Inspect generated Dockerfiles,
docker-compose.yaml, and.envplaceholders. - Kubernetes and Azure Kubernetes Service (AKS): make sure the production-serving resource becomes the workload with the service/ingress/gateway exposure. Build-only resources must be consumed by another deployable resource or converted with a JavaScript publish method.
- Azure Container Apps: only the production-serving compute resource should be external. For static browser apps,
PublishAsStaticWebsite(...)can be the external resource; for backend-served or gateway-served apps, the backend/gateway is the external resource. - Azure App Service: use this only when the JavaScript app fits the public website model and single target-port constraints. SSR/Node apps need the right startup script/output and external HTTP endpoint.
- AWS: verify support in the AWS integrations repo. Do not assume the AWS preview deployment supports every JavaScript publish mode.
Common pitfalls
- A Vite resource that works locally can fail deployment validation if it is still build-only and no deployed resource consumes its files.
- Vite dev-server proxy configuration does not automatically become production routing.
PublishWithContainerFiles(...)copies built files into a destination container; the destination app still needs to serve those files.PublishWithStaticFiles(...)is for gateway/BFF resources such as YARP serving frontend files.PublishAsPackageScript(...)keeps runtime package dependencies and is larger than a built Node server output; preferPublishAsNodeServer(...)when the framework emits a runnable server artifact.- Next.js standalone deployment requires Next.js standalone output configuration. Validate this before deploying.
- Do not expose both a dev frontend resource and the production-serving gateway/backend unless the user intentionally wants two public surfaces.
Kubernetes and Azure Kubernetes Service (AKS) deployment
Use this reference when the user asks for Kubernetes, Helm, kubectl, Azure Kubernetes Service (AKS), or cluster deployment.
Choose Kubernetes vs Azure Kubernetes Service (AKS)
Aspire has two Kubernetes paths:
| Target | Use when | Integration | Environment concept |
|---|---|---|---|
| Existing or externally-managed Kubernetes cluster | The cluster already exists, or the user explicitly wants a provider-managed cluster outside Aspire such as DigitalOcean Kubernetes (DOKS). Current kubectl context should point at the target cluster. | Kubernetes hosting | Kubernetes environment |
| Azure Kubernetes Service (AKS) | Aspire should provision Azure Kubernetes Service (AKS), ACR, identity, and Azure dependencies | Azure Kubernetes hosting | Azure Kubernetes Service (AKS) environment |
If the user says "Kubernetes" but not "Azure Kubernetes Service (AKS)", ask whether they want an existing/external cluster or a new Azure Kubernetes Service (AKS) cluster.
If the user names a non-Azure Kubernetes provider, such as DigitalOcean Kubernetes, use the existing/external Kubernetes path. Aspire will deploy into that cluster with Helm, but it does not own the provider's cluster or registry lifecycle unless a target-specific Aspire integration exists.
If the user says "Azure Kubernetes Service (AKS)", do not ask the existing-cluster question; use the Azure Kubernetes Service (AKS) path and also load the Azure reference for shared Azure settings.
Docs to load
Always start with current docs:
aspire docs search "Kubernetes deployment"
aspire docs search "Kubernetes hosting integration"
aspire docs get "deploy-to-kubernetes-clusters"
aspire docs get "kubernetes-integration"
aspire docs get "deploy-to-azure-kubernetes-service-aks"
aspire docs get "azure-kubernetes-service-aks-integration"
aspire docs search "Azure Kubernetes Service hosting integration"
aspire docs get "<slug>"Use API docs before editing. Search in the AppHost language you detected:
aspire docs api search "Kubernetes environment" --language csharp
aspire docs api search "Kubernetes environment" --language typescript
aspire docs api search "Helm" --language csharp
aspire docs api search "Helm" --language typescript
aspire docs api search "Kubernetes service customization" --language csharp
aspire docs api search "Kubernetes service customization" --language typescriptExisting or external Kubernetes cluster setup
Expected package and AppHost environment:
aspire add kubernetesAdd a Kubernetes environment resource using the C# or TypeScript API shape returned by Aspire docs.
For vanilla Kubernetes and externally-managed clusters, a container registry is required for project/container image deployment because Aspire has no local-registry fallback for Kubernetes. Cluster nodes must pull the built images.
Add a container registry resource to the AppHost using the language-specific API shape returned by Aspire docs. Aspire can use a single registry as the default target; use per-resource registry assignment only when different workloads must use different registries.
Verify the registry is reachable from both the agent machine and cluster nodes.
When the user asks to create a provider-managed cluster or registry outside Aspire, such as a DigitalOcean Kubernetes cluster and DigitalOcean Container Registry, confirm the billable resource choice first. After creation, configure kubectl, registry authentication, and any provider-specific registry-to-cluster integration before running aspire deploy.
Existing/external cluster code changes
Make these changes in the AppHost:
1. Run aspire add kubernetes if the AppHost does not already reference the Kubernetes hosting integration. 2. Add a Kubernetes environment resource.
C# AppHost shape:
var k8s = builder.AddKubernetesEnvironment("k8s");TypeScript AppHost shape:
const k8s = await builder.addKubernetesEnvironment("k8s");3. Add a container registry for project/container images, for example builder.AddContainerRegistry(...) in C# or the TypeScript equivalent returned by API docs. If one registry exists, Aspire can use it as the default target; use WithContainerRegistry(...) / withContainerRegistry(...) only when a specific resource should use a specific registry. 4. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each Kubernetes workload; in C#, add .WithComputeEnvironment(k8s) to each compute resource that should deploy to this cluster. 5. For TypeScript AppHosts, verify the current language-specific docs before assuming an equivalent assignment API. 6. Use k8s.WithHelm(...) / k8s.withHelm(...) only when the user needs chart name, release name, namespace, chart version, or other Helm settings. 7. Use k8s.AddGateway(...), k8s.AddIngress(...), or the TypeScript equivalents when public exposure is required. Otherwise services remain internal by default. For a simple public web frontend on a cloud Kubernetes provider, a per-resource LoadBalancer Service can be the direct exposure model; keep backend/internal services as ClusterIP.
- Routed endpoints must be marked external. Any endpoint exposed by an Ingress (
WithPath(...)) or a Gateway (WithRoute(...)), or wired up viaWithDefaultBackend(...), must come from a resource that opts in with.WithExternalHttpEndpoints()(C#) orisExternal: trueon the endpoint annotation.aspire publishfails fast with anInvalidOperationExceptionfromEndpointRoutingValidationif a non-external endpoint is routed, so always pairAddIngress/AddGatewayplumbing with explicit external opt-in on the target resource. This applies to AKS throughAzureKubernetesEnvironmentas well.
8. Use PublishAsKubernetesService(...) / publishAsKubernetesService(...) only for per-resource Kubernetes manifest customization.
Azure Kubernetes Service (AKS) setup
Expected package and AppHost environment:
aspire add azure-kubernetesAdd an Azure Kubernetes Service (AKS) environment resource using the C# or TypeScript API shape returned by Aspire docs.
Azure Kubernetes Service (AKS) deployment provisions Azure infrastructure, including Azure Kubernetes Service (AKS), ACR, managed identity, and Azure resources modeled in the AppHost.
Azure Kubernetes Service (AKS) creates an inner Kubernetes environment for Helm deployment and auto-creates an Azure Container Registry unless a registry is explicitly configured.
Azure Kubernetes Service (AKS) code changes
Make these changes in the AppHost:
1. Run aspire add azure-kubernetes if the AppHost does not already reference the Azure Kubernetes hosting integration. 2. Add an Azure Kubernetes Service (AKS) environment resource.
C# AppHost shape:
var aks = builder.AddAzureKubernetesEnvironment("aks");TypeScript AppHost shape:
const aks = await builder.addAzureKubernetesEnvironment("aks");3. Do not add explicit compute-environment assignment for the common single-environment case. Only if the AppHost has multiple compute environments, disambiguate each Azure Kubernetes Service (AKS) workload; in C#, add .WithComputeEnvironment(aks) to each compute resource that should deploy there. 4. Do not add a plain AddKubernetesEnvironment next to AddAzureKubernetesEnvironment for the same target. The Azure Kubernetes Service (AKS) environment owns the inner Kubernetes/Helm environment. 5. Let the integration create the default Azure Container Registry unless the user needs a specific registry. If they do, use the Azure Kubernetes registry customization API from current docs. 6. Use node pool/subnet/customization APIs only when required, for example WithSystemNodePool(...), AddNodePool(...), WithSubnet(...), or the TypeScript equivalents returned by API docs. 7. Use Kubernetes Gateway/Ingress APIs for public exposure; do not assume every service becomes public.
Preflight
For all Kubernetes targets:
kubectlis installed.helmis installed.- AppHost has the correct Kubernetes environment.
- AppHost parameters are configured or can be prompted.
- External exposure is explicit through Ingress, Gateway API, service customization, or target-specific defaults.
- Helm is the default deployment engine; record any customized namespace, release name, chart name, or chart version.
- Storage defaults are understood. Kubernetes defaults to
emptyDir; persistent storage needs explicit storage type/class/size decisions.
For existing/external clusters:
kubectl config current-contextpoints to the intended cluster.- Container registry is configured and reachable.
- Registry authentication is configured for image push from the agent machine.
- Image pull secret or registry auth is configured when the cluster cannot pull from the registry anonymously.
- Provider-specific registry attachment is configured when required, for example attaching a provider registry to a managed cluster.
- Namespace/release/chart settings are understood if Helm settings are customized.
For Azure Kubernetes Service (AKS):
- Azure CLI auth is available (
az loginfor local deploy). - Subscription, location, and resource group source are known.
Azure:SubscriptionId/Azure__SubscriptionIdandAzure:Location/Azure__Locationare configured or can be prompted.- Node pool defaults fit the target subscription/region, or the AppHost customizes node pools.
Preview and publish
Generate Helm artifacts without applying them:
aspire publish -o k8s-artifactsFor Azure Kubernetes Service (AKS), publish can also generate Azure infrastructure artifacts.
Inspect expected output:
Chart.yamlvalues.yamltemplates/- generated environment values for deploy-time parameter and image resolution
- Bicep infrastructure for Azure Kubernetes Service (AKS) targets when generated
Use list steps before deploy:
aspire deploy --list-stepsDeploy
Existing/external cluster:
aspire deployAspire uses current kubectl context and Helm. It deploys application resources into the cluster; it does not create or delete an externally-managed Kubernetes cluster or provider registry.
Azure Kubernetes Service (AKS):
aspire deployAspire provisions Azure resources, builds/pushes images to ACR, generates Helm charts, and installs them into Azure Kubernetes Service (AKS).
External Helm charts added to a Kubernetes environment install after the main app chart. They are not uninstalled by default during destroy because they may be shared; only treat them as owned by the Aspire app when the AppHost explicitly opts into destroy-time uninstall.
Destroy
Run the destroy pipeline for this AppHost/environment:
aspire destroy --environment <name>For an existing/external cluster, the destroy step runs against the configured cluster context for the selected AppHost/environment. Confirm the current kubectl context, namespace/release settings, and AppHost environment before running destroy. It does not delete an externally-created Kubernetes cluster, node pool, provider load balancer account resource, or container registry. Delete provider infrastructure with the provider CLI only when the user explicitly asks to remove that infrastructure too. For Azure Kubernetes Service (AKS), also confirm the Azure subscription and resource group because that target can own Azure infrastructure as well as cluster resources. Use --yes only after destructive intent is explicit. Use kubectl, cloud CLI, provider delete commands, or Helm only to diagnose failed teardown or remove leftovers that are not managed by the Aspire deployment target.
Native artifact handoff
If the user wants to apply published artifacts themselves:
helm install <release> ./k8s-artifacts
helm upgrade <release> ./k8s-artifactsUse values files or --set for environment-specific image tags and settings.
Exposure and TLS
By default, generated services use the Kubernetes environment's default service type, which is ClusterIP. Public access requires an explicit exposure mechanism such as Ingress, Gateway API, or service type customization. For cloud Kubernetes providers without an ingress controller configured, a frontend LoadBalancer Service is often the fastest public smoke-test path, while backend services should usually remain ClusterIP. Verify exact APIs in docs before editing because C# and TypeScript AppHost shapes differ.
Gateway/Ingress TLS can add extra deployment steps for bootstrap secrets, FQDN discovery, and field ownership cleanup. If a deployment fails around TLS or Gateway resources, inspect the listed pipeline steps and the generated manifests before changing the AppHost.
Troubleshooting
- Empty connection strings: inspect generated ConfigMaps and Secrets and verify env var names in pod specs.
- Password/auth failures: inspect Kubernetes Secrets and references; do not print secret values.
- ImagePullBackOff: verify image registry, pull secret/identity, and image tags.
- Azure Kubernetes Service (AKS) cluster unreachable: refresh credentials with
az aks get-credentials. - ACR pull issues on Azure Kubernetes Service (AKS): check ACR role assignment with
az aks check-acr. - Helm conflict on Gateway/TLS resources: inspect
helm status,kubectl describe gateway, and the generated Gateway/Ingress manifests.
Common deployment preflight
Use this reference for every Aspire deployment target.
AppHost discovery
Find the AppHost before choosing commands:
1. Run aspire ls first. It lists all AppHosts in the current scope and is the preferred discovery command. 2. If aspire ls shows exactly one AppHost, use it. 3. If aspire ls shows no AppHosts, stop deployment work and invoke the aspireify skill to initialize/wire the AppHost before continuing. 4. If aspire ls shows multiple AppHosts or discovery is still ambiguous, inspect aspire.config.json, *.AppHost.csproj, apphost.cs, or apphost.ts. 5. For C# project AppHosts, confirm the project references Aspire AppHost support. 6. For C# single-file AppHosts, look for the Aspire AppHost SDK directive. 7. For TypeScript AppHosts, look for the AppHost file and generated module support.
Use --apphost <path> when discovery is ambiguous, multiple AppHosts exist, or CI/CD should pin a specific AppHost. The path can point to an AppHost project file or supported single-file AppHost, such as apphost.cs.
Docs lookup checklist
Use Aspire docs search before changing target configuration:
aspire docs search "ci"
aspire docs search "github actions"
aspire docs search "deployment overview"
aspire docs search "deploy with Aspire"
aspire docs search "external parameters deployment"
aspire docs search "<target> deployment"
aspire docs get "<slug>"Use API docs before writing AppHost code. Search both languages until the AppHost language is known:
aspire docs api search "<method-or-resource>" --language csharp
aspire docs api search "<method-or-resource>" --language typescript
aspire docs api get "<id>"If aspire docs is unavailable, use official aspire.dev docs through the available web/documentation tools. Do not use outdated blog posts or workload-era docs as authority.
Target detection checklist
Inspect AppHost code for existing target environments. API names differ by AppHost language, so use these as concepts rather than exact names:
- Docker Compose environment
- Kubernetes environment
- Azure Container Apps environment
- Azure App Service environment
- Azure Kubernetes Service (AKS) environment
- AWS CDK environment
If none exists, ask for the deployment target unless the user's request clearly names one.
If more than one exists, ask which one to use or whether to deploy all.
Compute environment assignment
Aspire can infer the compute environment only when there is exactly one compute environment in the model. If multiple deployment environments exist, verify each compute resource is explicitly assigned to the intended environment before publishing or deploying.
Do not assume a resource deploys just because it appears in run mode. Resources hidden behind run-mode-only conditionals or assigned to a different compute environment will not be part of the target deployment.
Preview commands
Use these before applying changes:
aspire publish --list-steps
aspire deploy --list-stepsTreat --list-steps as a structural preview, not proof that a later deploy can run unattended. Some targets can emit deploy-time selection prompts that are not AppHost parameters, such as Azure tenant selection. If a prompt appears, answer it in a real interactive terminal/PTY; do not try to satisfy it by setting unrelated AppHost secrets unless the target docs explicitly define that mapping.
Use publish when the user wants to inspect generated artifacts:
aspire publish -o ./aspire-outputThe output path can be a scratch path if the user only asked for a preview. Do not commit generated deployment artifacts unless the user explicitly asks to keep them in source control.
When running a command that may prompt, do not pipe it through tee, tail, or similar output filters. Pipes can remove the interactive terminal that selection prompts require. Use the shell/session transcript or the CLI log file path printed by Aspire for diagnostics.
aspire publish and aspire deploy are related but not a two-step apply pipeline:
aspire publishgenerates target artifacts for review or handoff and leaves unresolved values as target-specific placeholders where possible.aspire deployresolves parameters and applies deployment steps directly from the AppHost model.- Running
aspire deploylater does not consume the directory produced by a previousaspire publish.
Use --environment <name> when the user wants a staging/production context other than the default. Deployment state and cached values are scoped by AppHost and environment, so changing the environment changes which cached values are used.
Destroying deployments
Use aspire destroy to run the AppHost deployment environment's destroy pipeline:
aspire destroy --environment <name>Treat destroy as a destructive deployment operation:
- Run it only when the user explicitly asks to tear down or clean up a deployment, or when a test workflow owns temporary infrastructure and teardown is part of that workflow.
- Use
aspire destroy --list-stepswhen practical to preview the teardown pipeline before applying it. - Confirm the AppHost, environment, target account/subscription/cluster, and resource group/namespace/stack context before applying.
- Use the same
--apphost <path>and--environment <name>values used for deployment when discovery or environment scope could be ambiguous. - Use
--yesonly for non-interactive teardown when destructive intent has already been approved, such as an explicit cleanup job. - Do not describe destroy as a Helm, Kubernetes, Docker, Azure, or AWS command. It is an Aspire command that delegates to the selected deployment target's destroy step.
- Keep target-native delete commands as troubleshooting or manual-leftover cleanup, not the primary teardown path for resources managed by the Aspire deployment target.
Parameters and secrets
Inventory parameter declarations. API casing differs by AppHost language:
- direct parameters
- secret parameters
- config-backed parameters
- connection string parameters
- target-specific parameter APIs
Report each parameter without revealing values:
| Field | What to report |
|---|---|
| Name | AppHost parameter name |
| Secret | whether it is marked secret |
| Source | environment variable, appsettings, user secrets, command line, prompt, CI secret |
| Consumer | project env var, connection string, Key Vault secret, Compose env, Helm Secret, Azure app setting |
| Status | configured, missing, generated, or unknown |
Use these conventions:
- AppHost parameter config key:
Parameters:name - Environment variable provider key:
Parameters__name - Parameter names with dashes use underscores in environment variables, for example
registry-endpointbecomesParameters__registry_endpoint - Local/dev-only AppHost secret command:
aspire secret set "Parameters:name" "<value>"
aspire secret set is a local/dev convenience today, not the deployment parameter path. For TypeScript AppHosts and non-interactive runs, set deploy-time values as environment variables on the aspire deploy process:
Parameters__name="<value>" \
aspire deploy --apphost ./apphost.ts --environment Production --non-interactiveNever print secret values. If a command prints secrets, redact them in any summary.
Deployment state can include resolved parameter values. Treat local deployment cache files and generated environment-specific artifacts as sensitive unless the target docs prove otherwise.
For CI/CD and GitHub Actions, load references/cicd.md before adding workflow YAML or pipeline commands.
External endpoints and production topology
Flag production-only endpoint behavior:
- External HTTP endpoint configuration can change what becomes public in deployment.
- JavaScript app resources need an explicit production serving model. Load
references/javascript.mdwhen the AppHost contains JavaScript, Vite, Node, or Next.js resources. - Azure Container Apps supports internal and external endpoints, with one main HTTP ingress group.
- Azure App Service supports a public website model with external HTTP/HTTPS endpoints only.
- Kubernetes exposes services through ClusterIP by default unless Ingress, Gateway API, or service type customization is configured.
Report what will be public, internal, or not exposed based on the target docs and AppHost code.
Run vs publish/deploy branching
Check for AppHost conditionals around execution context and environment:
- run mode vs publish/deploy mode
- development, staging, production, or custom environment checks
Explain when resources exist only locally or only in publish/deploy mode. If a resource is behind a run-mode-only branch, do not tell the user it will deploy.
Target-specific tools
Use target-native tools only after Aspire has produced artifacts or when verifying the result:
- Docker Compose: inspect generated Compose files or run Compose status commands against the generated project/files.
- Kubernetes: inspect Helm output and use kubectl/Helm against the target cluster.
- Azure: use Azure CLI for authentication and resource inspection, while keeping deployment through Aspire target environments.
- AWS: use AWS/CDK tooling required by the AWS Aspire integration.
Validation
After deployment, verify with target-appropriate checks:
- Docker Compose:
docker compose psagainst generated files or endpoint checks. - Kubernetes:
kubectl get pods,kubectl get svc,helm status, endpoint checks. - Azure: CLI output, Azure CLI resource inspection, endpoint checks, and dashboard URL when available.
Do not mark cloud deployment complete until provisioning, deployment, and at least one target-specific health or endpoint check succeeded.
Related skills
FAQ
What does aspire-deployment produce?
Aspire-native publish and deploy output for Docker Compose, Kubernetes, Azure, or AWS from the AppHost model.
When should I use aspire-deployment?
When an Aspire AppHost exists and the user wants to publish, deploy, or destroy a deployment target.
Is aspire-deployment safe to install?
Review the Security Audits panel on this page before installing in production.