Blog

Deploying ASP.NET 4.5 to Docker on Windows

01 Sep, 2016
Xebia Background Header Wave

At the moment of this writing you can search the internet on ASP.NET and docker and all you will find is how to deploy ASP.NET Core applications to a Linux docker container. Although I love the initiative of ASP.NET core, I do believe that ASP.NET 4.5 is something many of you know and love already and nobody talks about how we can leverage docker on windows to run this full version of ASP.NET

To get you started we need to have a Windows version that is capable of natively running docker. With natively running docker I mean that docker is build into the OS. So no use of docker for windows tools, since we don’t want Linux containers, we want to run windows containers! At this moment you can use Windows 10 Anniversary edition and Windows Server 2016 Technical Preview 5 to go through the steps that I describe here to get your ASP.NET 4.5 website running in a docker on windows container.

What do we need to rollout an ASP.NET website to a windows docker container?

When you run an ASP.NET 4.5 website then you need the following things:

  • The Operating system with IIS installed
  • ASP.NET 4.5 installed
  • Webdeploy installed

I personally love to use web deploy to deploy the website after build, so it can be done exactly the same way as you would deploy to Azure App Services or your local IIS Server on any server you already know and love.

Building the container with IIS, ASP.NET and Webdeploy

Here are the steps you need to take to create a docker container that has all these required ingredients:

Fist we need a basic operating system image from docker hub. For this you can run the following command from the command line:

docker pull microsoft/windowsservercore

now we have the image in our images gallery, you can check this with the following command:

docker images

This should output something similar to the following screenshot:

image

 

Now we can start adding the first layer and that is installing IIS. For this you can use the dism command on windows and pass it in the arguments to install the IIS webserver role to windows server core. You can do this at an interactive prompt or use the docker build command. I prefer the later and for this we create a dockerfile that contains the following statements:

FROM microsoft/windowsservercore 
RUN dism /online /enable-feature /all /featurename:iis-webserver /NoRestart

After saving the file under the name dockerfile without any extensions you run a command line to build the image:

docker build -t windowsserveriis .

The command tells docker to build an image, give it the tag windowsserveriis and use the current folder (denoted with the dot) as the context to build the image. this means that everything stated in the dockerfile is relative to that context. Note that you are only allowed to use lowercase characters for the tagename.

After running the command you now have a new docker image with the name windowsserveriis

If you now run the command:

docker images

you will see the new image available

image

We can take the next step and that is to install ASP.NET 4.5

We can do this in a similar way, by creating a docker file with the following commands:

FROM windowsserveriis
RUN  dism /online /enable-feature /featurename:IIS-ASPNET45

and again after saving the file you can run the command line to build the image:

docker build –t windowsserveriisaspnet .

Now we have an image that is capable of running an ASP.NET application. The next step is that we need webdepoy to be installed in the container. For this we need to download the installer for webdeploy and then issue an command that will install and wait for the installation to finish. We first download the installer in the same folder as the dockerfile and then we will add it to the image. In the following steps I assume you already downloaded the MSI (WebDeploy_2_10_amd64_en-US.msi) and have it in the same folder as the dockerfile. When installing the msi we will use msiexec and need to start a process that we can wait on to be done. If we would only run msiexec, then this command returns and runs in the background, making the container to exit, leaving us in an undefined state.

When you create the following dockerfile, you install webdeploy:

FROM windowsserveriisaspnet

RUN mkdir c:install

 

ADD WebDeploy_2_10_amd64_en-US.msi /install/WebDeploy_2_10_amd64_en-US.msi

 

WORKDIR /install

 

RUN powershell start-Process msiexec.exe -ArgumentList ‘/i c:installWebDeploy_2_10_amd64_en-US.msi /qn’ -Wait

Note that we are using powershell start-process with the –wait option, so we wait for the installation to finish, before we commit the new layer.

Now run the docker command again to build the image using the new dockerfile:

docker build –t windowsserveriisaspnetwebdeploy .

Now we have an image that is capable to host our website in IIS and use webdeploy to install our website.

Doing it all in one dockerfile

In the previous steps we created a new docker file for each step. But it is probably better to do this in one file, batching all commands together leaving you with the same endstate. We can also optimize the process a bit, since Microsoft already provides an image called microsoft/iis that has the iis feature enabled. This means we can use that image as the base layer and skip the install of IIS.

The simplified docker file looks as follows:

FROM microsoft/iis
RUN dism /online /enable-feature /all /featurename:iis-webserver /NoRestart
RUN mkdir c:install
ADD WebDeploy_2_10_amd64_en-US.msi /install/WebDeploy_2_10_amd64_en-US.msi
WORKDIR /install
RUN powershell start-Process msiexec.exe -ArgumentList '/i c:installWebDeploy_2_10_amd64_en-US.msi /qn' -Wait

Now again we run the docker build command to get the docker image capable of running our website and use the webdeploy packages that can be produced by a standard ASP.NET build procedure.

docker build –t windowsserveriisaspnetwebdeploy .

The final step is to deploy your webdeploy package to the image.

Getting the webdeploy package

Now before we can deploy our website we need to get the webdeploy package.

I assume you have a standard ASP.NET web project in Visual Studio. In this case you can very easily create the deploy package inside Visual Studio (in the next post I show you how to do this using VSTS/TFS builds)

When you right click the Visual Studio project you can select the publish option:

image

After selecting publish you will see the following dialog:

image

In order to just create a package in stead of deploying to a server or Azure, I select Custom

image

then you give the profile a name, in my case dockerdeploydemo

image

then we select web deploy package from the dropdown and provide the required information, package location and the name of the website

image

next you can setup any database connections if you have any, in my case I have no database

image

next, click publish and you will find the resulting deployment package and accompanying deployment files in the c:temp folder

image

Now that we have the webdeploy package and the accompanying deployment artifacts, we can again create a docker file that will then upload the package to the container and install the website in the container. This will then leave you with a complete docker image that runs your website.

Publish the website in the docker container

The dockerfile to deploy your website looks as follows:

FROM windowsserveriisaspnetwebdeploy 

RUN mkdir c:webapplication

WORKDIR /webapplication

ADD dockerdeploydemo.zip  /webapplication/dockerdeploydemo.zip

ADD dockerdeploydemo.deploy.cmd /webapplication/dockerdeploydemo.deploy.cmd
ADD dockerdeploydemo.SetParameters.xml /webapplication/dockerdeploydemo.SetParameters.xml

RUN dockerdeploydemo.deploy.cmd, /Y

We build the container again using the docker build command:

docker build –t mycontainerizedwebsite .

This now finally results in our web application in a container that we can then run on any windows server that has windows containers enabled.

Running the website in the container

In order to test if we succeeded we now issue the docker run command and then map the container port 80 to a port on our host. This can be done by using the –p option, where you specify a source and destination port. We also need to specify a command that ensures the container keeps running. For this we now use e.g. a command like ping –t which will result in an endless ping loop, that is enough to keep the container running. so to test the container we now run the following command:

docker run –p 80:80 mycontainerizedwebsite ping localhost -t

Now we can browse to the website. Be aware that you can only reach the container from the outside, so if you would browse to localhost, which results in the 127.0.0.0 you will not see any results. You need to address your machine on its actual hostname or outside IP address.

Summary

To summarize what we have done, we first created a docker image capable of running IIS, then we added ASP.NET 4.5, then we added webdeploy and finally we deployed our website to the container using webdeploy and the package generated by Visual Studio.

In the next post I will show you how we can use this image in build and release management using VSTS and then deploy the container to a server so we can run automated tests as a stage in the delivery pipeline.

Marcel de Vries
Marcel is a key figure in the technology sector, serving as the co-founder and Global MD & CTO of Xebia Microsoft Services. He is deeply involved in advancing organizational capabilities to deploy software swiftly and securely, emphasizing the importance of innovation and productivity while maintaining compliance. Marcel is passionate about technology and continuous learning, often sharing his insights at leading industry events and through online courses on Pluralsight. Recognized for his contributions, Marcel has been honored with the Microsoft MVP award for over 17 consecutive years and is a Microsoft Regional Director since 2008. His expertise spans across Cloud Adoption Strategies, DevOps, and various cloud computing frameworks, making him a respected voice in the tech community.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts