[ on ] chu .tech
← Blog

.NET Migration · 2026-06-01

Containerizing a Legacy .NET App: From Windows Server to Docker in 5 Steps

A five-step path for putting a legacy .NET Framework application into containers — base images, state, config, health checks, and the deployment order that does not require a rewrite.

You can containerize a legacy .NET Framework app without rewriting it. The five steps below are what I used to move Framework-era services onto Kubernetes — each step is small, reversible, and testable on its own.

1. Pick the base image honestly

.NET Framework apps need Windows containers: mcr.microsoft.com/dotnet/framework:4.8 as the runtime base. If that feels heavy, treat that as a signal — .NET 8 (or 6) with the same app logic often needs no rewrite at all, just the migration checklist. Decide the target before you touch a Dockerfile: Windows Server Core containers are fine for an internal service; they cost more and patch differently.

2. Make config external before you containerize

Config files baked into the image are a trap. Move connection strings, endpoints and feature flags to environment variables or a mounted config file first. The container image should be identical across environments — only the environment differs.

3. Handle state as the exception

If the app writes to local disk, that’s a problem containers will expose immediately. Move logs to stdout (Windows containers forward console output), move file caches to a shared volume or object storage, and treat the container filesystem as disposable. Sessions belong in a store, not on a local disk.

4. Give it a health check

A container that “runs” but serves 500s is worse than one that restarts. Add a lightweight HTTP endpoint (or TCP check) the orchestrator can probe:

HEALTHCHECK CMD powershell -Command "Invoke-WebRequest -UseBasicParsing http://localhost/health"

Then wire liveness and readiness in Kubernetes — and tune restartPolicy and terminationGracePeriodSeconds so the old app gets time to finish in-flight work.

5. Ship in the old/new order

Deploy order: build the image → run it side by side on a test port → point a canary at it → shift traffic → cut over. Keep the Windows Server host until the container has survived a full business cycle (patch cycles included). Retire it only when the container has proven it can take the load — not on day one.

The one-liner summary

Make config external, state disposable, and health checkable — and the container is just packaging. The rewrite debate can wait until the container is in production, where the real bottlenecks show themselves.

✉ Book a call