Sarıkaya Dev Logo

Deploy .NET 8 Minimal APIs to Azure Container Apps with Dapr

Mahmut Sarıkaya 4 min read 2 Views 0
Deploy .NET 8 Minimal APIs to Azure Container Apps with Dapr

What if you could launch a fully observable microservice in minutes?

Enter .NET 8 Minimal APIs, Azure Container Apps, and Dapr. Together they let developers ship lightweight HTTP endpoints, enable reliable pub/sub, and trace every request across services without writing boilerplate. The combination is especially powerful for teams that need rapid iteration and production‑grade observability.

Why .NET 8 Minimal APIs fit container workloads

Minimal APIs cut the ceremony of classic MVC controllers. A single Program.cs file can expose dozens of routes, keep the binary under 30 MB, and start in under a second. Azure Container Apps charges per vCPU‑second, so a lean image translates directly into lower cost. Moreover, .NET 8 adds native AOT support and improved garbage‑collection that reduces memory pressure in multi‑tenant clusters.

Preparing the Azure Container Apps environment

First, verify the Azure CLI version (>=2.45) and enable the Container Apps extension:

az version
az extension add --name containerapp

Create a resource group, a Log Analytics workspace for diagnostics, and the Container Apps environment:

az group create --name dapr-demo-rg --location eastus
az monitor log-analytics workspace create --resource-group dapr-demo-rg --workspace-name dapr-demo-law
az containerapp env create --name dapr-demo-env --resource-group dapr-demo-rg --location eastus --logs-workspace-id $(az monitor log-analytics workspace show --resource-group dapr-demo-rg --workspace-name dapr-demo-law --query id -o tsv)

These resources give you a secure place to host containers and a central place for distributed tracing data.

Adding Dapr sidecar and configuring Pub/Sub

Dapr runs as a sidecar process alongside your API container. The sidecar handles service invocation, state stores, and pub/sub without changing your code. In Azure Container Apps you enable Dapr with a single flag:

az containerapp create \
  --name dapr-minimal-api \
  --resource-group dapr-demo-rg \
  --environment dapr-demo-env \
  --image myregistry.azurecr.io/dotnet8-minimal:latest \
  --enable-dapr true \
  --dapr-app-id minimalapi \
  --dapr-app-port 8080 \
  --dapr-config "{{\"components\":[{\"type\":\"pubsub.kafka\",\"metadata\":[{\"name\":\"brokers\",\"value\":\"mykafka:9092\"}],\"name\":\"kafka-pubsub\"}]}}"

The JSON snippet declares a Kafka pub/sub component named kafka-pubsub. Replace the broker address with your own Azure Event Hubs for Kafka or a Confluent Cloud endpoint.

Implementing distributed tracing with OpenTelemetry

OpenTelemetry is the de‑facto standard for tracing. Add the NuGet packages OpenTelemetry.Exporter.OpenTelemetryProtocol and OpenTelemetry.Extensions.Hosting to your project. The following Program.cs configures tracing and registers Dapr client services:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Trace;
using Dapr.Client;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenTelemetryTracing(ot =>
ot.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddDaprInstrumentation()
.AddOtlpExporter(opts =>
{
opts.Endpoint = new Uri("http://localhost:4317");
}));

builder.Services.AddDaprClient();

var app = builder.Build();

app.MapGet("/weather", async (DaprClient dapr) =>
{
// Publish a weather event to Kafka
await dapr.PublishEventAsync("kafka-pubsub", "weather-events", new { Temp = 23, City = "Seattle" });
return Results.Ok("Event published");
});

app.Run();

The AddDaprInstrumentation call automatically creates spans for Dapr service invocations and pub/sub operations. Azure Monitor can ingest the OTLP stream directly when you enable the Log Analytics workspace as a trace sink.

Dockerizing the Minimal API

Keep the Dockerfile minimal to benefit from layered caching:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY *.csproj ./
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app --no-restore

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app .
EXPOSE 8080
ENTRYPOINT ["dotnet", "MinimalApi.dll"]

Build and push the image:

docker build -t myregistry.azurecr.io/dotnet8-minimal:latest .
docker push myregistry.azurecr.io/dotnet8-minimal:latest

Because the image only contains the runtime layer, the final size is roughly 70 MB, well under the 150 MB recommendation for Container Apps.

Deploying and validating the service

After the az containerapp create command finishes, retrieve the fully qualified domain name (FQDN) and call the endpoint:

FQDN=$(az containerapp show --name dapr-minimal-api --resource-group dapr-demo-rg --query properties.configuration.ingress.fqdn -o tsv)
curl https://$FQDN/weather

The response Event published confirms both the Minimal API and the Dapr sidecar are communicating correctly. Open the Log Analytics workspace, run a Kusto query on the traces table, and you will see a span hierarchy that starts at the ingress, flows through the API method, and ends at the Kafka publish call.

Best practices and performance tips

1. **Enable HTTP/2** on the Dapr sidecar (--dapr-http-port 3500) to reduce latency for service‑to‑service calls.
2. **Pin the .NET runtime** to the LTS version (8.0.6 as of March 2024) to avoid unexpected breaking changes.
3. **Turn on health probes** in Container Apps (--cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 5) so the platform can auto‑scale based on request latency.
4. **Export metrics** with AddPrometheusExporter if you need Grafana dashboards alongside Azure Monitor.

Conclusion

By coupling .NET 8 Minimal APIs with Azure Container Apps and Dapr, you gain a production‑ready stack that handles HTTP routing, pub/sub messaging, and distributed tracing with a handful of commands. The approach reduces operational overhead, improves cost efficiency, and provides end‑to‑end visibility—a compelling proposition for any C# microservice team.

Sources

Microsoft Docs – Azure Container Apps
Dapr Documentation – Pub/Sub and Service Invocation
OpenTelemetry .NET – Tracing Guide

Author: Mahmut Sarıkaya — sarikayadev.com

Tags: #dotnet 8 #minimal api #azure container apps #dapr #distributed tracing
Share:
M

Written by

Mahmut Sarıkaya

Software Developer

Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment

0 + 3 =