From Aspire to Docker Compose in one command

One of my favorite Aspire tricks is publishing your local orchestration to a plain Docker Compose file. No bespoke YAML hand-crafting: define your resources in C#, run one command, and get a production-shaped compose you can run anywhere Docker is available.

This post shows a tiny demo that publishes PostgreSQL, Redis, and the Aspire Dashboard to Docker Compose.

AppHost: enable the Docker publisher

var builder = DistributedApplication.CreateBuilder(args);

// Enables Docker publisher (gives the compose project a stable name)
builder.AddDockerComposeEnvironment("aspire-docker-demo");

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

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

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

builder. Build().Run();

What this does

  • AddDockerComposeEnvironment("aspire-docker-demo")
    Opts the app into the Docker publisher and sets the Compose project name (used for networks, volume names, etc.).
  • Postgres + volume
    WithDataVolume() ensures a named Docker volume is created for data durability.
  • AddDatabase("demo-db")
    Declares a logical DB (helpful when apps bind to it; not strictly needed for Compose output).
  • Redis
    Adds a simple cache service.

Publish to Docker Compose

From the AppHost directory:

aspire publish -o docker-compose-artifacts

This generates a docker-compose.yaml (and related files) under ./docker-compose-artifacts/.

Example output (trimmed for length)

services:
  aspire-docker-demo-dashboard:
    image: mcr.microsoft.com/dotnet/nightly/aspire-dashboard:latest
    expose: ["18888","18889"]
    networks: ["aspire"]
    restart: always

  database:
    image: docker.io/library/postgres:17.6
    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}
    expose: ["5432"]
    volumes:
      - type: volume
        target: /var/lib/postgresql/data
        source: dockerpublisher-...-database-data
    networks: ["aspire"]

  cache:
    image: docker.io/library/redis:8.2
    entrypoint: ["/bin/sh"]
    command: ["-c","redis-server --requirepass $$REDIS_PASSWORD"]
    environment:
      REDIS_PASSWORD: ${CACHE_PASSWORD}
    expose: ["6379"]
    networks: ["aspire"]

networks:
  aspire: { driver: bridge }

volumes:
  dockerpublisher-...-database-data: { driver: local }

A few details worth noting:

  • Aspire Dashboard is included by default so you can inspect logs/health even when running via Compose.
  • Secrets via env: DATABASE_PASSWORD and CACHE_PASSWORD are referenced as environment variables (read at docker compose up time).
  • Named volume for Postgres data provides persistence across container restarts.
  • Single network keeps services discoverable and isolated.

Why publish this way?

  • Parity: Your C# orchestration becomes a portable Compose file—perfect for teammate onboarding, CI smoke tests, or quick demos.
  • Security knobs: Compose uses env-vars for secrets; wire these to your secrets manager or CI variables.
  • Batteries included: You get the Aspire Dashboard out of the box for troubleshooting.

Next steps

  • Bind your actual apps (Web/API) to these resources and republish.
  • Add profiles or overrides for staging vs. prod (e.g., external ports, resource limits).
  • Push images to a registry in CI and use the published Compose as your single-file deployment recipe.

For more advanced pipelines and examples, see Aspire Pipelines by David Fowler:
https://github.com/davidfowl/AspirePipelines

[Source code]

That’s all folks!

Cheers!
Gašper Rupnik

{End.}

Leave a comment

Website Powered by WordPress.com.

Up ↑