This episode brings your application to production: Dockerizing .NET applications with multi-stage builds, deployment to Kubernetes, Azure, AWS, and GCP, managing configuration and secrets at runtime, and blue-green, canary release, and rollback strategies.

Code that passes tests is not yet production-ready. Episode 19 covers deployment and cloud native: wrapping .NET applications in containers, deploying to Kubernetes and cloud providers, managing configuration and secrets at runtime, and releasing new versions without downtime.
After this episode, you will have an application that does not just run on your machine, but lives in production infrastructure — with safe release strategies and the ability to roll back when something goes wrong.
An efficient .NET image is built in two stages: one for compilation, one for runtime. The Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "Catalog.Api.dll"]The build stage uses the SDK image to compile; the runtime stage only copies artifacts into the lightweight aspnet image. The result is a small image because it does not carry the SDK. This framework-dependent image needs the ASP.NET base image, which already contains the runtime.
Build and run the image:
docker build -t catalog-api:1.0.0 .
docker run -p 8080:80 catalog-api:1.0.0docker run -p 8080:80 maps host port 8080 to container port 80, where Kestrel listens. For non-root containers, use USER app in the Dockerfile — the .NET base image provides a secure app user by default.
Kubernetes manages containers with deployments, services, and scaling. An example manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: catalog-api
spec:
replicas: 3
selector:
matchLabels:
app: catalog-api
template:
metadata:
labels:
app: catalog-api
spec:
containers:
- name: catalog-api
image: registry.example.com/catalog-api:1.0.0
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /api/health
port: 80This deployment runs 3 replicas and checks health via a probe on /api/health — the endpoint we built in episode 11. Health probes matter: unhealthy Pods do not receive traffic.
dotnet runs natively on Linux.Choose managed Kubernetes for full control, or a managed platform to reduce operations. .NET applications run identically on all three because of containers.
Configuration is injected through environment variables (episode 10). In Kubernetes, use ConfigMaps and Secrets:
apiVersion: v1
kind: Secret
metadata:
name: catalog-secrets
stringData:
ConnectionStrings__Default: "Server=db;Database=Catalog"The ConnectionStrings__Default key maps directly to ConnectionStrings:Default in the application — no code changes needed. Secrets in Kubernetes are stored encrypted; for full production, consider integrating with a vault or a cloud provider.
Cloud-native applications follow 12-factor principles: configuration from the environment, statelessness, and restart readiness. .NET applications with the Generic Host and DI already support most of these principles naturally.
Blue-green runs two environments at once: the new version (green) is fully prepared, then traffic is switched after the health check passes. Rollback is moving traffic back to blue — instant and without downtime.
Canary sends a small portion of traffic to the new version while monitoring errors:
kubectl set image deployment/catalog-api \
catalog-api=registry.example.com/catalog-api:1.1.0
kubectl rollout status deployment/catalog-apikubectl rollout status monitors the gradual rollout. If the error rate rises, kubectl rollout undo returns to the previous version — automated rollback becomes a trusted emergency strategy. Canary is finer-grained than blue-green because the risk exposure is smaller.
Warning
Prepare the rollback from the start of a release: tag image versions clearly, keep the previous manifests, and make sure the database schema is compatible forward and backward.
Key takeaways:
In the next episode 20 we will discuss observability and production support — logging with Serilog, metrics, tracing, and OpenTelemetry integration, health checks and monitoring endpoints, and incident management, diagnostics, and production support readiness.