Using .NET Aspire With the Docker Publisher

Using .NET Aspire With the Docker Publisher

4 min read ·

AI Agents: The Future of Software Development AND Developers
AI Agents are redefining software, automating workflows and enabling real-time decisions via APIs. Join Postman's Rodric Rabbah for a free on-demand webinar that will get you up to speed on Agentic AI and explore how Postman Flows and AI Agent Builder can empower you to build, test, and deploy agents with APIs—no code required. Get up to speed on Agentic AI.

ReSharper's Fastest Build Yet Help us test ReSharper's fastest build yet: the 2025.2 EAP moves its engine out of Visual Studio and cuts median typing lag 37 %. Spin it up in an experimental VS instance and tell us if it's 🐞 or 👍 → Start here.

.NET Aspire is one of the most exciting additions to the .NET ecosystem in years.

It brings a fresh, modern approach to building cloud-native apps, with a focus on developer productivity, great defaults, and tight integration across your entire stack.

One of the most asked-for features is the ability to publish your app to Docker Compose. This is now available in the latest preview, and I'm excited to share how it works.

In this post, I'll walk you through how I used Aspire's Docker publisher to spin up a demo app that includes an API, a Postgres database, and a Redis cache. Everything runs using Docker Compose, and Aspire generates the whole thing from C# code.

I'll show you how to set it up, explain what it's doing behind the scenes, and give you a glimpse into how easy it is to take that setup and run it on a VPS or cloud server.

The Demo App

The app is intentionally simple, just enough to demonstrate how Aspire wires things together.

  • API project: a minimal .NET Web API
  • Postgres: used for data storage
  • Redis: used for caching

In a traditional setup, you'd manually connect these services, manage configuration files, handle environment variables, and write a docker-compose.yml from scratch.

With Aspire, you declare everything in C# inside the AppHost project. Here's a quick look at the setup:

var builder = DistributedApplication.CreateBuilder(args);

// Enables Docker publisher
builder.AddDockerComposeEnvironment("aspire-docker-demo");

var postgres = builder.AddPostgres("database")
    .WithDataVolume();

var database = postgres.AddDatabase("demo-db");

var redis = builder.AddRedis("cache");

var webApi = builder.AddProject<Projects.Web_Api>("web-api")
    .WithReference(database).WaitFor(postgres)
    .WithReference(redis).WaitFor(redis);

builder.Build().Run();

This gives you a development environment where Aspire runs Postgres and Redis in containers, and connects your API to them.

The AddDockerComposeEnvironment method enables the Docker publisher. It's available in the Aspire.Hosting.Docker NuGet package, which is currently in preview.

Install-Package Aspire.Hosting.Docker -Version 9.3.1-preview.1.25305.6

Installing the Aspire CLI

To publish your app to Docker Compose, install the Aspire CLI:

dotnet tool install --global aspire.cli --prerelease

Then you can run the publish command:

aspire publish -o docker-compose-artifacts

This command will scan your solution for the Aspire project and generate a Docker Compose file and an .env file based on the services you've defined.

Aspire publish command

The Docker Compose File

Let's examine what Aspire created for us:

services:
  database:
    image: 'docker.io/library/postgres:17.4'
    environment:
      POSTGRES_HOST_AUTH_METHOD: 'scram-sha-256'
      POSTGRES_INITDB_ARGS: '--auth-host=scram-sha-256 --auth-local=scram-sha-256'
      POSTGRES_USER: 'postgres'
      POSTGRES_PASSWORD: '${DATABASE_PASSWORD}'
    ports:
      - '8000:5432'
    volumes:
      - type: 'volume'
        target: '/var/lib/postgresql/data'
        source: 'aspire.apphost-1f0ed76b33-database-data'
        read_only: false
    networks:
      - 'aspire'
  redis:
    image: 'docker.io/library/redis:7.4'
    command:
      - '-c'
      - 'redis-server --requirepass $$REDIS_PASSWORD'
    entrypoint:
      - '/bin/sh'
    environment:
      REDIS_PASSWORD: '${REDIS_PASSWORD}'
    ports:
      - '8001:6379'
    networks:
      - 'aspire'
  web-api:
    image: '${WEB_API_IMAGE}'
    environment:
      OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES: 'true'
      OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES: 'true'
      OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY: 'in_memory'
      ASPNETCORE_FORWARDEDHEADERS_ENABLED: 'true'
      HTTP_PORTS: '8002'
      ConnectionStrings__demo-db: 'Host=database;Port=5432;Username=postgres;Password=${DATABASE_PASSWORD};Database=demo-db'
      ConnectionStrings__redis: 'redis:6379,password=${REDIS_PASSWORD}'
    ports:
      - '8003:8002'
      - '8005:8004'
    depends_on:
      database:
        condition: 'service_started'
      redis:
        condition: 'service_started'
    networks:
      - 'aspire'
networks:
  aspire:
    driver: 'bridge'
volumes:
  aspire.apphost-1f0ed76b33-database-data:
    driver: 'local'

This docker-compose file is generated from the C# code we wrote earlier. It defines the services, their images, environment variables, ports, and dependencies.

The .env file contains some of the configuration we need:

# Parameter database-password
DATABASE_PASSWORD=<YOUR_STRONG_PASSWORD>

# Container image name for web-api
# Change this to the imaage name in the container registry
WEB_API_IMAGE=web-api:latest

# Parameter redis-password
REDIS_PASSWORD=<YOUR_STRONG_PASSWORD>

It contains the passwords for the database and Redis, as well as the image name for the API. You'll need to replace the placeholders with actual values. For the API image, you can build and tag the image yourself, or use a pre-built one from a registry.

Publishing and Running on a VPS

Aspire doesn't deploy the app for you, but it gives you everything you need.

Once the Compose file is ready, deployment to a VPS is straightforward:

  1. Copy the artifacts to your server using (scp or git).
  2. SSH into the VPS.
  3. Run docker compose up -d inside the artifact directory.

Make sure Docker and Docker Compose are installed on the server.

You can expose ports with a reverse proxy like Nginx or Caddy, and secure it with HTTPS using Let's Encrypt.

I'll cover this in more detail in a future post.

Wrapping Up

.NET Aspire with Docker Compose provides a smooth developer experience and a simple way to deploy full-stack apps.

You define everything in C#, test it locally, and publish it with one command. No need to write Compose files or manage infrastructure manually. This opens up new possibilities for deploying and managing cloud-native apps. You're not locked into a specific cloud provider, and you can easily move between environments.

Can I just say how much I love this? I'm really excited about the future of cloud-native development with .NET and Aspire.

If you liked this article and want to learn how I structure larger apps, check out Modular Monolith Architecture. It walks you through building clean, scalable .NET applications with strong internal boundaries and maintainability in mind.

Thanks for reading and stay awesome!


Whenever you're ready, there are 4 ways I can help you:

  1. (NEW) Pragmatic REST APIs: You will learn how to build production-ready REST APIs using the latest ASP.NET Core features and best practices. It includes a fully functional UI application that we'll integrate with the REST API.
  2. Pragmatic Clean Architecture: Join 4,000+ students in this comprehensive course that will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture.
  3. Modular Monolith Architecture: Join 2,000+ engineers in this in-depth course that will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario.
  4. Patreon Community: Join a community of 1,000+ engineers and software architects. You will also unlock access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses.

Become a Better .NET Software Engineer

Join 68,000+ engineers who are improving their skills every Saturday morning.