Passenger

Containers and Aspire

Debug and profile .NET services in Docker Compose and Aspire

A container is one more place a .NET service runs. Passenger runs a compose file's services, a Dockerfile's or an Aspire app's as one, every .NET service under its debugger, Hot Reload and profiler, with nothing to set up beyond the files you have. Free and open source, on Windows, macOS and Linux.

An Aspire AppHost debugged in Passenger: the API service stopped at a breakpoint with its values after the lines, a Debug tab for each service, and the Aspire window listing both services running with the API's details

Docker Compose and Dockerfiles

Passenger works through your own docker command and whatever its context reaches: Docker Desktop, Colima, OrbStack, Rancher Desktop, Podman or a remote engine.

Containers are run configurations

Each compose file with its override, each project with a Dockerfile, each project that asks the .NET SDK for its image, and each Docker Compose project (.dcproj) is found as the solution opens. Docker, DockerCompose and SdkContainer launch profiles run. Edit Configurations chooses Run, Debug or Don't start for each .NET service.

Fast, or as deployed

By default Passenger builds the .NET services itself and runs each from its build, mounted into its image's runtime stage: a code change needs no image rebuild, and Rerun restarts only the services whose build changed, on the same ports. Or run the images as Compose builds them.

Every service debugged at once

Debug holds each .NET service at its start, attaches Passenger's debugger inside its container and lets it go, so a breakpoint in Main stops. Each gets a Debug tab with its container's log as its console. Run with Hot Reload applies your edits to every service as it runs, and an edit it can't apply rebuilds and restarts only the service that holds it.

One service at a time

From a service's row in the Containers window, or the run icon beside it in the compose file: debug it, attach to it, run it without the debugger, restart or profile it while the others run on. A service marked Don't start can be started later in the same run.

Attach to Process, inside containers

Attach to Process lists the .NET programs in every running container, those Passenger didn't start too, and debugs the one you choose there.

Profiled where it runs

CPU traces and memory snapshots are taken in the container and shown as any others: hot spots at their lines, snapshots compared. Profile records a service from its first instruction, Attach Profiler one already running.

The Containers window

Compose projects with their services, then every other container, images, volumes and networks, each with its state, health and ports as links: start, stop, restart, pull, scale, prune and inspect, a container's log with Find, its stats, files and details, and a shell in a Terminal tab.

Logs and traces from a compose app

Turn on Collect logs and traces and Aspire's dashboard runs beside your services: their structured logs and traces show in the Containers window's Telemetry tab, a request's spans put together across services.

Code help in Dockerfiles and compose files

Language servers for both, BuildKit's own checks, and Compose's own reading as you type: errors on their lines, each ${VAR} followed by what it comes to (a secret as dots), Go to Declaration, Rename and completion of services, volumes and networks, and fixes for a name nothing declares. A connection string a service reads but never gets is warned of, with its fix.

Add Docker Support and Compose

A Dockerfile and .dockerignore for a project, or the SDK's container properties, and a compose.yaml with the backing services your packages call for (Postgres, SQL Server, MongoDB, Redis, RabbitMQ), each with a healthcheck and its connection string. Undo takes either back.

The IDE of your Aspire AppHost

An AppHost, a project or a single-file apphost.cs, is a run configuration, and Aspire's orchestrator asks Passenger to start each project resource, so every .NET service runs under Passenger.

Run, debug, reload and profile the whole app

Debug debugs every service at once, a Debug tab each, or those you mark. Hot Reload reaches each; Profile records the service you choose from its first instruction. Rerun builds and restarts only what changed, the AppHost too when its own code did.

The Aspire window

The AppHost's resources with their state, health and addresses, their details with secrets masked, their consoles merged into one log with Find, the structured logs and traces they send, and the AppHost's own log. A resource's commands run from its row, and the AppHost's prompts come up as dialogs.

Code help across the AppHost

Resource names complete, AddProject goes to its project, and a connection string's name in a service goes to the AppHost line that declares it. A service that reads a connection string its AppHost never gives it is marked with a fix that adds the WithReference, and Rename renames a resource everywhere it is read.

Its containers go with it

The containers an AppHost makes are listed under it in the Containers window and removed with the run, however it ends. A container you made Persistent stays yours. Add › Aspire Orchestration adds an AppHost to a solution that has none.

What your services ask of the database

The Requests window follows the services of a compose run or an AppHost, as it follows a program you run: each request they serve, the SQL each ran, N+1s and slow commands marked. The Migrations window works on the database the run uses, at the port the engine published it on.

Requests, SQL and migrations
Passenger's Requests window following an Aspire app's ASP.NET Core API as it runs, under the minimal API handler that loops over the plants: each GET /plants/thirsty request marked N+1, its repeated SQL query marked ×6 with its reads and times

Good to know

  • Linux containers. Windows containers aren't supported; while Docker Desktop runs them, the status bar says so.
  • Podman works with Docker's command and Compose v2 on its socket, or alone with podman compose running Docker's Compose v2.
  • The container tools Passenger debugs and profiles with are downloaded for the container's system (Linux x64 or Arm64, glibc or musl) from the release the first time, checked against its checksums.
  • Aspire 13.6 or a later 13.x.