Deploy a .NET web app on Amazon ECS

Indrachapa
8 min readMar 2, 2022

Let’s look at how to deploy a .NET web application on Amazon ECS.

In this blogpost i will share with you:

  • Create a AWS Cloud9 environment using AWS ClouFormation.
  • Create a Docker image and push it to ECR
  • Create an ECS cluster
  • Deploy the app
  • Configure monitoring and logging.

As you know AWS Cloud9 is an online IDE. there is no upfront cost to use this IDE. AWscloudFormation is a service that gives an easy way to create a collection of related AWS resources.

ECR is a fully managed container registry offering high-performance hosting. You can deploy application images and artefacts anywhere. ECS is a fully managed container orchestration service that makes it easy for you to deploy, manage and scale containerized apps.

Create CloudFormation stack

First, we need to configure an environment using AWS CloudFromation template. This template describes all the resources and dependencies. So we can launch and configure them as a stack. You can use this template to create the stack. Then, Go to the AWS CloudFormation console and begin to create a stack.

In create stack page choose Template is ready as Prerequisite — Prepare template. In specify template tab there are 2 options. One is you can upload the template to S3 and can provide the S3 url in the given box or you can upload the template file. Click on Next and in the next page, you can specify the stack name, network configuration and RDS configuration.

After providing all details click next. Now you are in the configure stack options page. Here we don’t have to make any changes. Just go to the review screen. Check and review all the details you provided and make sure to tick all the checkboxes inside Transforms might require access capabilities.

Capabilities and transforms

Click on create stack. Now you can see the status of your stack. Just check Events, Resources and Outputs to get an idea about all information about the resources created by the cloudFormation template.

Cloud9 Workspace

After your CloudFormation stack is completed check the Outputs tab. You can find your Cloud9 IDE workplace lick on the given URL and go to the workspace. For the rest of the tutorial, I’m going to use a sample application. This sample application dependencies need more space that what is allocated with Cloud9. We have to increase the partition size using these commands. You can use Cloud9 bash to run these commands.

sudo growpart /dev/xvda 1

sudo resize2fs /dev/xvda1

And Download the sample application. Try following the command in the Cloud9 terminal.

git clone https://github.com/aws-samples/amazon-ecs-dotnet-app-graviton.git

Build Docker Image

Before creating the ECR repository we need to set up environment variables in Cloud9. Go to the cloud9 IDE again and configure the AWS CLI with the current region.

export AWS_REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/region)

aws configure set default.region ${AWS_REGION}

aws configure get default.region

Set up environment variables for AWS account id,

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity — query Account — output text)

echo $AWS_ACCOUNT_ID

Now we can create an ECR repository to store docker image. You can choose any name for the repository.

export IMAGE_REPO_URI=$( \

aws ecr create-repository \

— repository-name movie-app-repo \

— query repository.repositoryUri \

— output text \

)

echo Repo URI: $IMAGE_REPO_URI

After running this command you can see the image repository URI on the bash terminal.

You will need this URI when you specify the container definition in the ECS Task definition in the next steps.

Before creating a Dockerfile move to the source code directory.

cd ~/environment/amazon-ecs-dotnet-app-graviton/app/

Now create the Dockerfile in the project.

touch Dockerfile

Now open the docker file. You can use nano, vi, or Cloud9 IDE to edit the file. Then copy the following commands and paste them into your docker file. Make sure to save it.

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build

WORKDIR /src

# These lines copy MvcMovie.csproj project files in the current directory

# and then restore for the specified runtime, using -r.

COPY [“MvcMovie.csproj”, “./”]

RUN dotnet restore “MvcMovie.csproj” -r linux-musl-arm64

# Build dotnet project and publishes the application and its dependencies to a folder for deployment to a hosting system.

COPY . .

WORKDIR “/src/.”

RUN dotnet publish “MvcMovie.csproj” -c Release -o /app/publish -r linux-musl-arm64 — self-contained false — no-restore

# Docker build command

# You need to use an architecture-specific tag if you want to target ARM based instances.

# Note that .NET is only supported on Alpine on ARM64 and x64, and not ARM32.

FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine-arm64v8

WORKDIR /app

EXPOSE 80

COPY — from=build /app/publish .

ENTRYPOINT [“dotnet”, “MvcMovie.dll”]

Build and publish the docker images with a tag. Tag your image with the ECR registry. Run these commands to complete that task.

docker build -t movie-app .

docker tag movie-app $IMAGE_REPO_URI

Check the image is created successfully

docker images movie-app

As the last step, we need to publish the Docker image. You need to log in to the ECR repository and publish the new image you built in the previous step. Hope you remember we created environment variables earlier. We have to use them now. In the following command replace your AWS account id with $AWS_ACCOUNT_ID and replace the region with $AWS_REGION.

aws ecr get-login-password | docker login — username AWS — password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com

Now, build your docker image using following command

docker build -t movie-app-repo .

After build completes, tag your image then you can push the image to repository. Make sure to replace you aws account id and the region in the command before run it.

docker tag movie-app-repo:latest aws_account_id.dkr.ecr.region.amazonaws.com/movie-app-repo:latest

Push this image to the repository

docker push aws_account_id.dkr.ecr.region.amazonaws.com/movie-app-repo:latest

Using this command you can find the information about the image in the repository

aws ecr describe-images — repository-name movie-app-repo

Create an Amazon ECS cluster

Navigate to the AWS Elastic container service console. Click on create cluster button and in the select cluster template page choose EC2 Linux + Networking go ahead with the next step. In the Configure cluster page, we need to configure the details related to the cluster.

Cluster details should be like this:

Cluster name : Graviton2ECSCluster

EC2 Instance type : t4g.medium

Number of instances: 1

In the networking section:

VPC : select TargetVPC from the dropdown

Subnets: TargetVPC-private-a-web and TargetVPC-private-b-web

Security Group: ECSServiceSG

In the Container instance IAM Role section:

Container instance IAM role: select Create new role from the dropdown

CloudWAtch Container Insights: Tick the Enable container insights check box

Now create the cluster!

After cluster creating completed need to create ECS Task Definition. On the left side navigation page, you can find an option for Task definitions. Go to Task Definition and select EC2 as Select launch type compatibility. Click on the Next step button and move to Configure task and container definitions page.

To create task and container definition enter the following values.

Task definition name: Graviton2ECSTask

Task role: none

Task execution IAM role: ContainerizeDotNetOnECSGraviton2-ECSTaskExecutionRole or use can use the name suggested at the beginning of this process

Task memory: 512

Task CPU: 1024

In Container Definition, click Add Container. Then input these values to create a container.

Container name: Graviton2Container

Image: put your IMAGE_REPO_URI. (should be look like <AWS_ACCOUNT_ID>.dkr.ecr.<AWS_REGION>.amazonaws.com/movie-app-repo:latest)

Port mapping: 0, 80

Next, you have to add environment variables for the container to access the Database instance. Check the outputs tab on the CloudFormation console. You can find the RDSSecretARN . copy it because you will need it to create environment variables.

In the Environment section add following environment variables.

Key

Value/ValueFrom

Value

DBHOST

ValueFrom

<RDSSecretARN from CloudFormation Outputs>:host::

DBNAME

ValueFrom

<RDSSecretARN from CloudFormation Outputs>:dbname::

DBUSER

ValueFrom

<RDSSecretARN from CloudFormation Outputs>:username::

DBPASS

ValueFrom

<RDSSecretARN from CloudFormation Outputs>:password::

DBSSLMODE

Value

none

Under storage and logging section tick the Log Configuration — Auto-configure CloudWatch Logs checkbox. Leave the rest of the things as it is and click on Add button. Now you are back on the Task definition page. Click on Create button to create the task definition. Again go to Clusters and click on your cluster name from the list. In the services, you’ll see no services there. It means that your Task definition is complete but no tasks are running yet.

Deploy the app to Amazon ECS

Go to your cluster and under the services tab click the Deploy button. Expand Compute Configuration (advanced) section. Since you have an existing cluster it should already be selected. Then select EC2 as Launch Type. now under Deployment configuration select Service and select Graviton2ECSTask as Task definition — Family from the dropdown. Revision should be LATEST.

Give Graviton2ECSService as your service name or you can use preferable name for your service. Enter value ‘2’ for desired tasks.

Let’s move to creating a load balancer. In the Load balancing — optional section, select create new load balancer and enter a name. Ensure Listener Port is 80 and Protocol HTTP. then give a name to the Target group and select HTTP as the protocol.

In the Networking boundaries, select TargetVPC from the dropdown. Then you have to choose public subnets. Under Security group, select Use an existing security group and choose the security group which is you created in the beginning using CloudFormation template. It looks like <CloudFormation-Stack-Name>-ALBSG security group. Now you can leave rest of the things to default and move with click on Deploy button. Oce it finished you can see the Tasks running, Health check status and notifications.

Since its completed, we need to enable session management for this application. Here we take the simplest route by enabling sticky session. Elastic load balancers support sticky sessions. Navigate EC2 console and click on Targe groups from Load balancing section. Choose the name of the target group use created in the previous step. On the Group details tab, in Attributes section, click on Edit. select Stickiness. For Stickiness type, select Load balancer generated cookie and leave the default value is 1 days as Stickiness duration. Now Save changes.

Now you can test the deployment! Staying on EC2 console, click on Load balancers then select Load balancer name. Copy the value of DNS Name from the description. Open that copied URL in a new browser window. That’s the sample application we deployed. Try login to the application using credentials.

Username: admin

Password: Pass@word1

This last step completed the deployment of your .Net app on Amazon ECS.

Logging and Monitoring

First confirm container insights is enabled. If you missed enabling container insights you can enable it using this command.

aws ecs update-cluster-settings — cluster Graviton2ECSCluster — settings name=containerInsights,value=enabled — region ${AWS_REGION}

In the “settings”, “name” should be “containerIsights” nad “value” — “enabled”. Go to the CloudWatch console to visualize container insights. Click on Container Insights under the Insights section. Select List View. now you can see the list of the container resources. Click on each of the resources to see the metrics.

Cluster metrics provide the view of the CPU utilization, Network transferred and Memory management. It also provides a view of number of container instance, task and service within the cluster.

Service metrics provide a view of the aggregated metrics of the tasks running and also the performance for each of the tasks.

Task metrics give you a view of the metrics for each task running in the cluster

On the CloudWatch console click to on Log Group under Logs to view logs. Select ”/ecs/<your-ecs-TaskName>” which is the log group that was created in the previous deployment step. Select that log group to show log streams from the containers in the ECS tasks. Select a log stream to view the application logs. On the screen, you can specify filters based on date and time to retrieve logs.

finally, if you are done with the process you can clean up the resources you created.

--

--