Migrating Legacy ASP.NET apps to Docker

Many organizations, not wanting to rewrite applications, are figuring out how to take apps and containerize them for the cloud. Older operating systems are either end-of-life or approaching the end-of-life. Likewise, applications are increasingly being migrated to cloud hosts. The need to do this is as pressing as ever and containers offer a simple, viable solution to make this happen. Windows Containers on Docker bring to bear is the ability to “modernize” legacy .NET apps.

Containers by design improves application density on a given hardware by eliminating the need for redundant operating system installs. Unlike virtual machines that provide hardware abstraction on which a guest OS and apps are installed, containers provide operating system level abstraction, and apps run on top of that. This in effects removes all the CPU and memory requirements needed to run individual OS’s for apps and consolidates this into a single operating system (or multiple if running on a cluster). In the end, the savings are realized in terms of disk space, CPU, and memory consumption.

migrating apps to docker

Microsoft like many other organizations have embraced containers, and have formed a deep partnership with Docker to provide Windows containers. Moving legacy apps to containers is nuanced, and there is no one-size-fits-all approach, but this guide is intended to provide a high-level approach to getting your legacy ASP.NET apps into Windows containers. The basic steps for migrating a ASP.NET app to container involves:

  1. Installing Docker
  2. Pulling a Base Image
  3. Customizing the Base Image to Run the App
  4. Running the App
  5. Deploying the App

A working example of this tutorial is available here.

Installing Docker for Windows

Docker for Windows is a set of tools that can be deployed onto Windows 10 for development and testing purposes. These tools can be downloaded and installed. Alternatively, these steps can also be performed on a Windows 2016 Server with Docker installed. Production apps, however, will need to be run on Windows Server 2016 – we’ll cover this later.

Pulling a Base Image

Every container starts with a base image. Microsoft has provided two base images for containers: Windows Server Core and Windows Nano Server. Each of these editions are extensible, but for legacy .NET apps, Nano Server will not work because it does not support the full .NET framework. The .NET framework’s dependencies are well outside the scope of what is available in Nano Server. Server Core however has everything needed to get legacy .NET apps up and running.

Pulling an image simply refers to downloading that image to your local computer, and this can easily be done with the Docker CLI. Microsoft has a number of base images on Docker Hub that can be used as a starting point for your app. For legacy ASP.NET apps, the best image to use is the ASP.NET image provisioned for .NET 3.5, which can also run ASP.NET 2.0 and 1.X apps.

docker pull microsoft/aspnet:3.5

Customizing the Base Image to Run the App

Customizing an image is done with a Dockerfile. The file starts FROM a a base images and adds and configures and application and application-specific dependencies in the image. Classic ASP.NET apps need the .NET 3.5 runtime to run.

FROM microsoft/aspnet:3.5
ADD MyOldSChoolDotNetApp /inetpub/wwwroot/

Create a folder on your computer called docker-app, then copy this stub into a text editor and save it as Dockerfile (without an extension) in the folder you create. Copy the folder for your app into the docker-app folder your created. Make sure MyOldSchoolDotNetApp matches the name of your app. Your folder structure will look something like the following:

    |   |-bin
    |   |   |-myapp.dll
    |   |   |-...
    |   |-defualt.aspx
    |   |-web.config
    |   |...

If you need to install other dependencies, you can also place these in the same folder. Use an ADD command in the Dockerfile to move these into the image. Likewise, you can use the add command to download dependencies from the internet by specifying the URL (ie. ADD mydep.exe). Use the RUN command to install these. You’ll want to use a quiet install (most of the time this is a /q flag on the installer) with installed dependencies.

ADD my-dependecy.msi /my-dependecy.msi
RUN msiexec /i /q my-dependecy.msi

The next step is to build the image. In the command line, CD to the docker-app folder and run docker build.

docker build --no-cache -t myoldschoolapp .

The -t parameter is the name of the image. If all goes well, the image will build locally. If something doesn’t work, look at the console for error output and tweak the Dockerfile accordingly to resolve these issues. Much of the work in customizing images is debugging the Dockerfile to make sure everything gets installed correctly.

Running the App

After completing the build, it is time to run the app. You can do this by simply running the docker run command with a few simple parameters. This will start the container in a detached mode with a name of myoldschoolapp1.

docker run -dit --name myoldschoolapp1 -p 80:80 myoldschoolapp

Once the container is started, you can run a command to get the IP address of the container.

docker inspect --format '{{ .NetworkSettings.IPAddress }}' myoldschoolapp1

Now, copy that IP address, and point a browser to it with by prepending it with http://

If all goes well, you should see the app come up in a browser.

Deploying the App

To deploy your app, you’ll need an environment that can support Windows containers. You can install Windows Container support on Windows Server with a few simple. Refer to the Install Docker section in this document.

Once installed, you’ll need a Docker Hub account. You can sign up for one here. After creating the account, you can push the image to Docker Hub, but first you’ll need to tag it. Tagging it tells Docker what repository to store the image in. Insert you Docker ID

docker tag myoldschoolapp <YOUR DOCKER ID>/myoldschoolapp

Now, login to Docker.

docker login

This will prompt your for credentials. Login. Now, you can push the image to Docker Hub.

docker push <YOUR DOCKER ID>/myoldschoolapp

Once pushed, you can pull the new image from Docker Hub to your production environment. If this is a private image, your can set it to private by selecting Settings in the Docker Hub portal for the repository, then select Make Private.

docker pull <YOUR DOCKER ID>/myoldschoolapp

After pulling it, you can run it just like you did after building it.


Migrating ASP.NET apps to Docker usually isn’t an arduous process. The hardest part usually us figuring out which base image to use and how to customize it. For most apps built on pure ASP.NET dependencies, no additional software is needed beyond what comes installed in the base image. The trick is learning to “think Docker” and then lift-and-shift accordingly.

0 comments on “Migrating Legacy ASP.NET apps to DockerAdd yours →

Leave a Reply

Your email address will not be published. Required fields are marked *

twenty − twenty =