Minimal API Workshop
Module 5
Aspire, Containers & Shipping
AppHost · dashboard · containers · versioning
3:45 – 4:40 PM
By the end you can
- Orchestrate the API and its dependencies locally with Aspire
- See the day's telemetry in the dashboard
- Build a container image with no Dockerfile
- Version the API before the first client
What Aspire is — and is not
- Is: local orchestration, service discovery, a dashboard
- Is not: a deployment target
- It produces a manifest that tools like
azddeploy - Aspire itself runs on your laptop
The AppHost
var builder = DistributedApplication.CreateBuilder(args);
var payments = builder.AddProject<Projects.Roastery_Payments>("payments");
builder.AddProject<Projects.Roastery_Api>("api")
.WithReference(payments)
.WithExternalHttpEndpoints();
builder.Build().Run();
WithReference injects the payment address; service discovery resolves https://payments.
ServiceDefaults
builder.AddServiceDefaults(); // OTel, health, discovery, resilience
// ...
app.MapDefaultEndpoints(); // /health and /alive
One extension every service calls. The OTel + health code from Lab 4 moves here.
The dashboard payoff
- Place an order → open Traces
- The EF queries, the call to
payments, the retry spans - The
OrderReadyNotifierlog, correlated by trace id - Nothing added to make this visible — it was already there
A container image — no Dockerfile
dotnet publish src/Roastery.Api -c Release \
--os linux --arch x64 /t:PublishContainer
# base image, non-root user, port 8080 — all chosen for you
docker run -p 8080:8080 -e Jwt__SigningKey=$KEY roastery-api
Double-underscore env vars map to config sections. Same code, laptop → container → cloud.
Version before the first client
builder.Services.AddApiVersioning(o =>
{
o.DefaultApiVersion = new ApiVersion(1);
o.ReportApiVersions = true;
});
var v1 = app.MapGroup("/api/v{version:apiVersion}")
.WithApiVersionSet(versions).MapToApiVersion(1);
v1.MapProductEndpoints();
URLs become /api/v1/…; a v2 endpoint lives beside v1 with no change to v1's code.
The deployment landscape
| Target | How |
|---|---|
| Azure Container Apps | azd up from the Aspire manifest |
| Kubernetes | Aspire manifest → manifests / Helm |
| Any container host | The image + environment variables |
The instructor plays a recorded azd up — conference Wi-Fi has ended more demos than bad code.
Lab
Lab 5 · Run It Like Production
- Add the AppHost + ServiceDefaults; move OTel/health into defaults
- Find the order's trace, retry spans, and notifier log in the dashboard
- Build the container image and version the API as v1 + v2
Ends at checkpoint-5
Minimal API Workshop
Wrap-up
You built Roastery.
Architecture review · retrospective · where to go next
4:40 – 5:00 PM