13 Replatforming the legacy: Packaging and running Windows apps in Docker
This chapter makes the case for replatforming legacy Windows applications into Docker as a fast, low-risk path to the cloud that avoids costly rewrites while unifying build, deployment, and operations with modern tooling. It explains the key differences of Windows Server Containers versus Linux: they run only on Windows and require an exact OS version match between host and image; base images are much larger (Server Core vs Nano Server); and containers tend to start more slowly with many background services. Despite these quirks, the core Docker workflows are the same: write a Dockerfile, build images, push to a registry, and run containers with consistent commands and practices.
Practically, the chapter shows how to package Windows apps by choosing appropriate Microsoft base images (IIS, .NET Framework, ASP.NET, Server Core, Nano Server) and automating deployment via two main patterns: installing MSI packages in a multi-stage build or extracting file archives with PowerShell, curl, and tar. Because many Windows platforms run as Services, it introduces Service Monitor and Log Monitor to align service lifecycles and logging with Docker’s single-process model. It demonstrates building and running an unchanged, decade-old ASP.NET app (Nerd Dinner) using .NET Framework SDK and runtime images, then models the full stack with Docker Compose, including startup ordering via healthchecks. For data, it uses SQL Server in containers and packages the database schema as a DACPAC, enabling both clean deployments and in-place upgrades through the same immutable artifact—bringing CI/CD discipline to database changes.
Strategically, the chapter situates Windows containers within a broader migration framework: retire, rehost, replatform, refactor, and rewrite. It argues that replatforming is often the best first step for complex or low-change legacy systems—delivering cloud portability, operational consistency, and a foundation for later refactoring—while avoiding the risk, cost, and time of a full rewrite. It also cautions to plan for OS version compatibility and image size, and to weigh when a modernization to cross‑platform .NET and Linux containers makes sense. The result is a pragmatic path: use Windows containers to lift valuable legacy apps into modern, observable, reproducible workflows today, and evolve them iteratively based on business value tomorrow.
Multi-platform image variants include an OS version for Windows images.
Running the Windows web server (IIS) in a Windows Server Container
Packaging a Windows Docker image by installing an MSI in the Dockerfile
Looking at the processes in a Windows container shows a lot more than in Linux.
Monitor tools run a legacy application the way it was designed, but behaving like an ordinary container.
Welcome to 2013! Nerd Dinner running in an ASP.NET Windows container
Welcome to 2013! Nerd Dinner running in an ASP.NET Windows container
Packaging a SQL database in a Docker image lets you run a containerized database, or use a container to upgrade an existing database server.
Running the database container deploys the DACPAC, which creates all the objects.
The full Nerd Dinner experience, running in the latest Windows Server Containers
Lab
Nice replatforming lab for you here—it’s going to take a bit of investigation, but that’s always the way for legacy app migration. An MSI installer file in the lab directory for this chapter deploys an ASP.NET web application. Your goal is to get this app running correctly in Docker with Windows Server Containers. You’ll need to write a Dockerfile for the web app and a Compose spec to run the app and the database. Here are a few things you’ll need to know:
- The app connects to a SQL Server database. An empty database is fine, but the app configuration is fixed in the MSI. It expects to find a database at the DNS address SIGNUP-DB-DEV01, and it uses the sa user account with the password DockerCon!!!
- It’s a web application that will run with the IIS Windows Service (which is called w3svc), but it needs .NET Framework 4.8 installed.
- The app writes logs to a file at C:\logs\SignUp.log. We want those published as container logs—you’ll need to install the LogMonitor tool as part of your deployment. There’s a LogMonitorConfig.json in the lab folder, which is correctly configured, and you’ll need to copy that into the Docker image and set the correct entry point.
- Deploying the MSI is the easiest part—it doesn’t need any configuration settings passed in; you can just install it with the msiexec tool.
- When you have everything running, you should be able to browse to the app at http://localhost:8088/signup and see a newsletter sign-up page. If you click the Sign Up button and fill in the details, you should see logs in the web container, and the data will be stored in the SQL Server container.
As always, there are solution files in the lab folder, and a bit more detail in the README file: https://github.com/sixeyed/diamol/blob/2e/ch13/lab/README.md.
Learn Docker in a Month of Lunches, Second Edition ebook for free