Ir al contenido
Docs Try Aspire

Deploy your first app — TypeScript AppHost

Esta página aún no está disponible en tu idioma.

In this tutorial, you take the app you created in the Build your first Aspire app — TypeScript AppHost quickstart and deploy it. This can be broken down into several key steps:

  1. Add deployment package — Add the hosting package for your target.
  2. Update your AppHost — Configure the environment API.
  3. Deploy your app — Deploy using the Aspire CLI.
  4. Verify your deployment — Ensure your app is running as expected.
  5. Clean up resources — Remove any deployed resources to avoid incurring costs.

The following diagram shows the architecture of the sample app you’re deploying:

architecture-beta
  group docker(logos:docker-icon)[NodeJS and static site server container]  

  service api(logos:nodejs-icon)[API service] in docker
  service http(iconoir:server-connection)[https] in docker
  service frontend(logos:react)[React front end] in docker

  frontend:L --> R:http
  http:L --> R:api

The React (Vite) & Express starter template consists of two resources that are deployed as a single container. The Express server hosts both the API and the static frontend files generated by React.

Depending on where you want to deploy your Aspire app, ensure you have the following prerequisites installed and configured:

Docker logo

In the root directory of your Aspire app that you created in the previous quickstart, add the appropriate hosting deployment package by running the following command in your terminal:

Docker Compose is a tool for defining and running multi-container Docker applications. It allows you to use a YAML file to configure your application’s services, networks, and volumes, making it easier to manage and deploy complex applications locally or in various environments.

Aspire CLI — Add Docker Compose
aspire add docker

The Aspire CLI is interactive, be sure to select the appropriate search result for the 📦 Aspire.Hosting.Docker version you want to add.

If prompted for additional selections, use the Up Arrow Up Arrow Up Arrow and Down Arrow Down Arrow Down Arrow keys to navigate the options. Press Return Enter Enter to confirm your selection.

Learn more about the aspire add command in the reference docs.

In the AppHost, chain a call to the appropriate environment API method to configure the deployment environment for your target.

TypeScript — apphost.ts
import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
// Add the following line to configure the Docker Compose environment
await builder.addDockerComposeEnvironment("env");
const app = await builder
.addNodeApp("app", "./api", "src/index.ts")
.withHttpEndpoint({ env: "PORT" })
.withExternalHttpEndpoints();
const frontend = await builder
.addViteApp("frontend", "./frontend")
.withReference(app)
.waitFor(app);
await app.publishWithContainerFiles(frontend, "./static");
await builder.build().run();
  • addDockerComposeEnvironment — Configures the Docker Compose environment for deployment. This call implicitly adds support for containerizing resources in the AppHost as part of deployment.
  • withExternalHttpEndpoints — Exposes HTTP endpoints for the resource when deployed.

Now that you’ve added the deployment package and updated your AppHost, you can deploy your Aspire app.

Deploying to Docker Compose builds the container images and starts the services locally using Docker Compose.

Aspire CLI — Deploy your app
aspire deploy

Consider the following example output:

Example output for deploying Express/React app to Docker Compose
Aspire CLI - Deploy Express/React app with Docker Compose
13:23:29 (pipeline execution) → Starting pipeline execution...
13:23:29 (publish-env) → Starting publish-env...
13:23:29 (build-prereq) → Starting build-prereq...
13:23:29 (deploy-prereq) → Starting deploy-prereq...
13:23:29 (build-prereq) ✓ build-prereq completed successfully
13:23:29 (deploy-prereq) i [INF] Initializing deployment for environment 'Production'
13:23:29 (publish-env) i [INF] Generating Compose output
13:23:29 (deploy-prereq) i [INF] Setting default deploy tag 'aspire-deploy-20251107192329' for compute resource(s).
13:23:29 (deploy-prereq) ✓ deploy-prereq completed successfully
13:23:29 (build-frontend) → Starting build-frontend...
13:23:29 (build-frontend) i [INF] Building container image for resource frontend
13:23:29 (build-frontend) i [INF] Building image: frontend
13:23:29 (publish-env) → Writing the Docker Compose file to the output path.
13:23:29 (publish-env) ✓ Docker Compose file written successfully to ./aspire-app/aspire-output/docker-compose.yaml. (0.0s)
13:23:29 (publish-env) ✓ publish-env completed successfully
13:23:29 (publish) → Starting publish...
13:23:29 (publish) ✓ publish completed successfully
13:23:51 (build-frontend) i [INF] docker buildx for frontend succeeded.
13:23:51 (build-frontend) i [INF] Building image for frontend completed
13:23:51 (build-frontend) ✓ build-frontend completed successfully
13:23:51 (build-app) → Starting build-app...
13:23:51 (build-app) i [INF] Building container image for resource app
13:23:51 (build-app) i [INF] Building image: app
13:24:07 (build-app) i [INF] docker buildx for app succeeded.
13:24:07 (build-app) i [INF] Building image for app completed
13:24:07 (build-app) ✓ build-app completed successfully
13:24:07 (build) → Starting build...
13:24:07 (build) ✓ build completed successfully
13:24:07 (prepare-env) → Starting prepare-env...
13:24:07 (prepare-env) ✓ prepare-env completed successfully
13:24:07 (docker-compose-up-env) → Starting docker-compose-up-env...
13:24:07 (docker-compose-up-env) → Running docker compose up for env
13:24:13 (docker-compose-up-env) ✓ Service env is now running with Docker Compose locally (5.6s)
13:24:13 (docker-compose-up-env) ✓ docker-compose-up-env completed successfully
13:24:13 (print-env-dashboard-summary) → Starting print-env-dashboard-summary...
13:24:13 (print-app-summary) → Starting print-app-summary...
13:24:13 (print-env-dashboard-summary) i [INF] Successfully deployed env-dashboard to http://localhost:54633.
13:24:13 (print-app-summary) i [INF] Successfully deployed app to http://localhost:54463.
13:24:13 (print-env-dashboard-summary) ✓ print-env-dashboard-summary completed successfully
13:24:13 (print-app-summary) ✓ print-app-summary completed successfully
13:24:13 (deploy) → Starting deploy...
13:24:13 (deploy) ✓ deploy completed successfully
13:24:13 (pipeline execution) ✓ Completed successfully
------------------------------------------------------------
13/13 steps succeeded Total time: 44.1s
Steps Summary:
44.0 s pipeline execution
22.2 s build-frontend
16.3 s build-app
5.6 s docker-compose-up-env
0.0 s publish-env
0.0 s deploy-prereq
0.0 s build-prereq
0.0 s print-env-dashboard-summary
0.0 s print-app-summary
0.0 s deploy
0.0 s build
0.0 s prepare-env
0.0 s publish
PIPELINE SUCCEEDED
------------------------------------------------------------

When you call aspire deploy, the Aspire CLI builds the container images for your resources, pushes them to the target environment (if applicable), and deploys the resources according to the configuration in your AppHost.

Additional information about this command can be found in the aspire deploy reference docs.

After a deployment, the Aspire CLI writes to the provided output path (or the default output path if none is provided) a set of files based on your deployment target. This may include files such as Docker Compose files, Kubernetes manifests, or cloud provider-specific configuration files.

  • Directorioaspire-output
    • .env
    • .env.Production
    • app.Dockerfile
    • docker-compose.yaml

The aspire-output directory contains the generated environment variables, an app.Dockerfile, and the Docker Compose configuration. The best part is, these files are opaque to you as a developer—you don’t need to write them yourself!

The app.Dockerfile is generated as a multi-stage Dockerfile to build the Express API and also serve the React front end:

./aspire-output/app.Dockerfile
ARG FRONTEND_IMAGENAME=frontend:latest
FROM node:22-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
FROM ${FRONTEND_IMAGENAME} AS frontend_stage
FROM node:22-slim AS app
COPY --from=frontend_stage /app/dist /app/./static
COPY --from=builder /app /app
USER node
WORKDIR /app
ENTRYPOINT ["node", "--import", "tsx", "src/index.ts"]

Finally, the docker-compose.yaml file defines the service:

./aspire-output/docker-compose.yaml
services:
env-dashboard:
image: "mcr.microsoft.com/dotnet/nightly/aspire-dashboard:latest"
expose:
- "18888"
- "18889"
networks:
- "aspire"
restart: "always"
app:
image: "${APP_IMAGE}"
environment:
PORT: "8000"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://env-dashboard:18889"
OTEL_EXPORTER_OTLP_PROTOCOL: "grpc"
OTEL_SERVICE_NAME: "app"
ports:
- "8000"
networks:
- "aspire"
networks:
aspire:
driver: "bridge"

To verify that your application is running as expected after deployment, follow the instructions for your chosen deployment target below.

When deploying to Docker Compose, the aspire deploy command displays the URLs where your services are running. Look for the print-*-summary steps in the deployment output, which show the localhost URLs for each service that has been configured with withExternalHttpEndpoints.

In the deployment output, you’ll see lines similar to the following:

Aspire CLI - Deployment summary
13:24:13 (print-env-dashboard-summary) i [INF] Successfully deployed env-dashboard to http://localhost:54633.
13:24:13 (print-app-summary) i [INF] Successfully deployed app to http://localhost:54463.

Open your web browser and navigate to the URL shown for your app (for example, http://localhost:54463) to see your deployed application.

Deployed Express/React application running in Docker Compose

The front end displays the weather forecast data in a stunning React template. In this example, both the API service and the React front end are running within the same Docker container.

After deploying your application, it’s important to clean up resources to avoid incurring unnecessary costs or consuming local system resources.

To clean up resources after deploying with Docker Compose, you can stop and remove the running containers using the following command:

Aspire CLI - Stop and remove containers
aspire do docker-compose-down-env

For a deep-dive into the related foundational concepts, see Pipelines and app topology.

You’ve just built your first Aspire app and deployed it to production—congratulations! 🎉 Now you might be wondering: “How do I make sure all these services actually work together correctly?” That’s where integration testing comes in. Aspire makes it easy to test your entire application stack, including service-to-service communication and resource dependencies. Ready to learn how? Write your first test