Containerizing a .NET 4.x Application for AWS
Tags: dotnet, aws, docker
Published: 2022-06-23 15:24:04

In this post we are going to demonstrate ways in which you can containerize your applications for deployment into the cloud, the next step in minimizing resource usage and likely saving money. This article is different from the previous entries in this series because those were a discussion of containers and running them within the [AWS](https://aws.amazon.com) infrastructure while this post is much more practical and based upon getting to that point from an existing non-containerized application.

##Using Visual Studio

Adding container support using Visual Studio is straightforward.

###Adding Docker Support

Open an old ASP.NET Framework 4.7 application or create a new one. Once open, right-click on the project name, select **Add**, and then **Docker Support** as shown in Figure 1.

![Figure 1. Adding Docker Support to an application.](https://billthevestguy.com/wp-content/uploads/2022/06/image.png)_Figure 1. Adding Docker Support to an application._

Your Output view, when set to showing output from Container Tools, will show multiple steps being performed, and then it should finish successfully. When completed, you will see two new files added in the Solution Explorer, **Dockerfile**, and a subordinate **.dockerignore** file. You will also see that your default Debug setting has changed to Docker. You can see both changes in Figure 2.

![Figure 2. Changes in Visual Studio after adding Docker support.](https://billthevestguy.com/wp-content/uploads/2022/06/image-1.png)_Figure 2. Changes in Visual Studio after adding Docker support._

You can test the support by clicking the Docker button. This will build the container, run it under your local Docker Desktop, and then open your default browser. This time, rather than going to a localhost URL you will instead go to an IP address, and if you compare the IP address in the URL to your local IP you will see that they are not the same. That is because this new IP address points to the container running on your system.

Before closing the browser and stopping the debug process, you will be able to confirm that the container is running by using the Containers view in Visual Studio as shown in Figure 3.

![Figure 3. Using the Containers view in Visual Studio to see the running container](https://billthevestguy.com/wp-content/uploads/2022/06/image-2.png)_Figure 3. Using the Containers view in Visual Studio to see the running container._

You can also use [Docker Desktop](https://www.docker.com/products/docker-desktop/) to view running containers. Open Docker Desktop and select **Containers** / **Apps**. This will bring you to a list of the running containers and apps, one of which will be the container that you just started as shown in Figure 4.

![Figure 4. Viewing a running container in Docker Desktop](![Image description](https://billthevestguy.com/wp-content/uploads/2022/06/image-3.png)_Figure 4. Viewing a running container in Docker Desktop._ 

Once these steps have been completed, you are ready to save your container in ECR, just as we covered earlier in the series.

## Deploying your Windows Container to ECR

However, there are some complications with this, as the AWS Toolkit for Visual Studio does not support the container deployment options we saw in an earlier article when working with Windows containers. Instead, we are going to use the [AWS PowerShell tools](https://aws.amazon.com/powershell/) to build and publish your image to ECR. At a high level, the steps are:

-_Build your application in Release mode_. This is the only way that Visual Studio puts the appropriate files in the right place, namely the obj\Docker\publish subdirectory of your project directory. You can see this value called out in the last line of your Dockerfile: COPY ${source:-obj/Docker/publish} .
-_Refresh your ECR authentication token_. You need this later in the process so that you can login to ECR to push the image.
-_Build the Docker image_. 
-_Tag the image_. Creates the image tag on the repository
-_Push the image to the server_. Copy the image into ECR

Let’s walk through them now. The first step is to build your application in Release mode. However, before you can do that, you will need to stop your currently running container. You can do that through either Docker Desktop or the Containers view in Visual Studio. If you do not do this, your build will fail because you will not be able to override the necessary files. Once that is completed, your Release mode build should be able to run without problem.

Next, open PowerShell and navigate to your project directory. This directory needs to be the one that contains the Docker file. First thing we will do is to set the authentication context. We do that by first getting the command to execute, and then executing that command. That is why this process has two steps.

```
$loginCommand = Get-ECRLoginCommand -Region <repository region>
```

And then 

```
Invoke-Expression $loginCommand.Command
```

This refreshed the authentication token into ECR. The remaining commands are based upon an existing ECR repository. You can access this information through the AWS Explorer by clicking on the repository name. This will bring up the details page as shown in Figure 5.

![Figure 5. Viewing a running container in Docker Desktop](https://billthevestguy.com/wp-content/uploads/2022/06/image-4.png)_Figure 5. Viewing a running container in Docker Desktop._ 

The value shown by the 1 is the repository name and by number 2 is the repository URI. You will need both of those values for the remaining steps. Build the image:

```
docker build -t <repository> .
```

The next step is to tag the image. In this example we are setting this version as the latest version by appending both the repository name and URI with “:latest”.

```
docker tag <repository>:latest <URI>:latest
```

The last step is to push the image to the server:

```
docker push <URI>:latest
```

You will see a lot of work going on as everything is pushed to the repository but eventually it will finish processing and you will be able to see your new image in the repository.

_**Note**: Not all container services on AWS support Windows containers. Amazon ECS on AWS Fargate is one of the services that does as long as you make the appropriate choices as you configure your tasks. There are detailed directions to doing just that at [https://aws.amazon.com/blogs/containers/running-windows-containers-with-amazon-ecs-on-aws-fargate/](https://aws.amazon.com/blogs/containers/running-windows-containers-with-amazon-ecs-on-aws-fargate/)._

While Visual Studio offers a menu-driven approach to containerizing your application, you always have the option to containerize your application manually.

## Containerizing Manually

Containerizing an application manually requires several steps. You’ll need to create your Docker file and then coordinate the build of the application so that it works with the Docker file you created. We’ll start with those steps first, and we’ll do it using JetBrains Rider. The first thing you’ll need to do is to add a Docker file to your sample application, called **Dockerfile**. This file needs to be in the root of your active project directory. Once you have this added to the project, right-click the file to open the _Properties_ window and change the **Build action** to _None_ and the **Copy to output directory** to _Do not copy_ as shown in Figure 6.

![Figure 6. Build properties for the new Docker file](https://billthevestguy.com/wp-content/uploads/2022/06/image-5.png)_Figure 6. Build properties for the new Docker file._

This is important because it makes sure that the Docker file itself will not end up deployed into the container.

Now that we have the file, let’s start adding the instructions:

```
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
ARG source
WORKDIR /inetpub/wwwroot
```

These commands are defining the source image with **FROM**, defining an argument, and then defining the directory and entry point where the code is going to be running on the container. The source image that we have defined includes support for ASP.NET and .NET version 4.8, _mcr.microsoft.com/dotnet/framework/aspnet:4.8_, and is being deployed onto Windows Server 2019, _windowsservercore-ltsc2019_. There is an image for Windows Server 2022, windowsservercore-ltsc2022, but this may not be usable for you if you are not running the most current version of Windows on your machine.

The last part that we need to do is to configure the Docker file to include the compiled application. However, before we can do that, we need to build the application in such a way that we can access these deployed bits. This is done by publishing the application. In Rider, you publish the application by right-clicking on the project and selecting the **Publish** option. This will give you the option to publish to either a _Local folder_ or _Server_. This brings up the configuration screen where you can select the directory in which to publish as shown in Figure 7.

![Figure 7. Selecting a publish directory](https://billthevestguy.com/wp-content/uploads/2022/06/image-6.png)_Figure 7. Selecting a publish directory._


It will be easiest if you select a directory underneath the project directory; we recommend within the bin directory so that the IDEs will tend to ignore it. Clicking the **Run** button will publish the app to the directory. The last step is to add one more command to the Dockerfile where you point the source command to the directory in which you published the application.

```
COPY ${source:-bin/release} .
```

Once you add this last line into the Dockerfile, you are ready to deploy the Windows container to ECR using the steps that we went through in the last section.

Now that we have walked through two different approaches for containerizing your older .NET Framework-based Windows application, the next step is to do the same with a .NET Core-based application. As you will see, this process is a lot easier because we will build the application onto a Linux-based container so you will see a lot of additional support in the IDEs. Let’s look at that in our next post.