Introduction

Deploying a .NET application to the cloud involves more than running the application on a server. Networking, security, containers, databases, load balancing, logging, monitoring, and infrastructure management must work together.

In this hands-on AWS project, I deployed a containerized .NET web application using AWS managed services and explored how different AWS components work together to create a scalable and monitored application.

The deployment covers the complete application lifecycle:

  • Creating the network and security foundation

  • Containerizing the .NET application

  • Storing the Docker image in Amazon ECR

  • Running the application using ECS Fargate

  • Exposing the application through an Application Load Balancer

  • Connecting the application securely to Amazon RDS

  • Monitoring the application with CloudWatch

  • Sending alerts through SNS

  • Scaling ECS tasks

  • Defining the infrastructure using CloudFormation

Architecture

The application follows this basic request flow:

Code
Browser
   |
   | HTTP :80
   v
Application Load Balancer
   |
   | HTTP :8080
   v
ECS Fargate
   |
   | Database connection
   v
Amazon RDS

The supporting AWS services are:

  • Amazon VPC: Provides the isolated network environment.

  • Subnets: Separate public and private resources.

  • Security Groups: Control communication between the ALB, ECS, and RDS.

  • Amazon ECR: Stores the .NET application's Docker image.

  • Amazon ECS Fargate: Runs application containers without requiring EC2 server management.

  • Application Load Balancer: Provides the public entry point and distributes traffic to healthy ECS tasks.

  • Amazon RDS: Hosts the relational database in private networking.

  • Amazon CloudWatch: Provides centralized logging, metrics, dashboards, and alarms.

  • Amazon SNS: Sends email notifications when CloudWatch alarms are triggered.

  • ECS Container Insights: Provides additional ECS task and container monitoring information.

  • AWS CloudFormation: Defines infrastructure as code so the environment can be recreated consistently.

What I Implemented

The project was implemented in multiple stages.

First, I created the VPC, subnets, security groups, IAM roles, CloudWatch log group, and SNS notification resources.

Next, I containerized the .NET application and pushed the Docker image to Amazon ECR. I then created an ECS Fargate cluster and task definition, configured the container resources and logging, and deployed the application as an ECS service.

An Application Load Balancer and target group were configured to route incoming HTTP requests to healthy ECS tasks.

For persistence, I created an Amazon RDS MySQL/PostgreSQL database in private networking. Database access was restricted so that only the application tier could communicate with it.

The application consumed the database configuration through the ECS task configuration, and the task definition was updated accordingly.

Finally, I explored ECS scaling, CloudWatch monitoring, SNS notifications, Container Insights, and CloudFormation.

Step-by-Step AWS Configuration

1. Create a VPC

A VPC provides an isolated network environment in AWS where subnets, routing, and network access can be controlled.

The VPC is the foundation for the rest of the deployment.

2. Create Subnets

A subnet is a smaller network segment inside the VPC.

The deployment uses different subnet roles:

  • Public Subnet: Used for the Application Load Balancer.

  • Private/Application Subnet: Used for the ECS Fargate application.

  • Private DB Subnet: Used for Amazon RDS.

The separation allows public-facing and internal resources to be placed in different network segments.

3. Create Security Groups

Security groups control network traffic to the different components.

ALB-SG

The load balancer security group controls incoming traffic to the Application Load Balancer.

Example:

Code
Inbound:
Protocol: HTTP
Port: 80
Source: 0.0.0.0/0

ECS-SG

The ECS security group controls traffic going to the application containers.

Code
Inbound:
Protocol: TCP
Port: 8080
Source: ALB-SG

This means the ECS application accepts application traffic from the load balancer rather than directly from the internet.

RDS-SG

The RDS security group controls access to the database.

For MySQL:

Code
Inbound:
Protocol: TCP
Port: 3306
Source: ECS-SG

For PostgreSQL:

Code
Inbound:
Protocol: TCP
Port: 5432
Source: ECS-SG

The overall request flow is:

Code
Internet
   |
   | HTTP :80
   v
ALB
   |
   | TCP :8080
   v
ECS
   |
   | DB Port
   v
RDS

The database port depends on the selected database engine:

  • MySQL: TCP 3306

  • PostgreSQL: TCP 5432

4. Create IAM Roles

ECS commonly uses two different IAM roles for different purposes.

ECS Task Execution Role

The task execution role allows the ECS/Fargate infrastructure to perform actions required to start the task, such as pulling the container image from ECR and sending container logs to CloudWatch.

Code
ECS/Fargate
   |
   +----> ECR
   |      Pull Docker image
   |
   +----> CloudWatch
          Send container logs

ECS Task Role

The task role is used by the application code running inside the container when it needs to call AWS services.

For example, if the .NET application needs to access an AWS service directly, the required permissions should be assigned to the task role using the principle of least privilege.

Keeping the execution role and task role separate makes the IAM configuration easier to understand and control.

5. Create a CloudWatch Log Group

Create a CloudWatch log group where ECS container logs will be centralized.

Example:

Code
/aws/ecs/my-application

Centralized logging makes it easier to troubleshoot application and container issues.

6. Create an SNS Topic

Amazon SNS is used to send notifications when a CloudWatch alarm is triggered.

Example:

Code
aws-assignment-alerts

The notification flow is:

Code
CloudWatch Alarm
       |
       v
     SNS
       |
       v
    Email

7. Create an ECR Repository

Amazon Elastic Container Registry (ECR) is a managed container image registry.

The Docker image is built locally and pushed to ECR.

Code
Local Machine
      |
      | docker build
      v
Docker Image
      |
      | docker push
      v
Amazon ECR

ECR stores the image that ECS Fargate later pulls when starting the application task.

8. Create an ECS Cluster

Amazon Elastic Container Service (ECS) runs containers using either Fargate or EC2.

In this project, ECS Fargate is used so the application can run without managing the underlying EC2 servers.

Create an ECS cluster configured for Fargate workloads.

9. Create an ECS Task Definition

A task definition describes how ECS should run the Docker container.

The task definition includes configuration such as:

SQL
Task Definition
   |
   +-- Image: ECR
   +-- CPU
   +-- Memory
   +-- Port: 8080
   +-- Logging: CloudWatch
   +-- Execution Role
   +-- Task Role (when required)

The task definition provides the configuration ECS uses when starting the application container.

10. Create an Application Load Balancer

The Application Load Balancer provides the public entry point to the application and distributes HTTP requests to healthy ECS tasks.

Configure the ALB to listen on port 80 and attach the ALB security group.

Code
Internet
   |
   | HTTP :80
   v
Application Load Balancer

For a production deployment, HTTPS should normally be configured on the load balancer using an appropriate TLS certificate.

11. Create a Target Group

The target group identifies where the ALB should send application traffic and performs health checks on the targets.

The flow is:

Code
ALB
 |
 | HTTP
 v
Target Group
 |
 | Port 8080
 v
ECS Tasks

The target group health check helps the load balancer determine whether an ECS task is ready to receive traffic.

For example, if the .NET application exposes a health endpoint, the target group can use:

Code
Protocol: HTTP
Port: 8080
Health Check Path: /health

The exact health-check path should match an endpoint implemented by the application.

12. Create an ECS Service

The ECS service is responsible for maintaining the desired number of running tasks.

It also integrates the ECS tasks with the load balancer.

The basic configuration is:

Code
ECS Cluster
     |
     v
Task Definition
     |
     v
Fargate Service
     |
     v
Desired Task Count

Navigate to the ECS cluster and create the service using the task definition.

13. Configure Networking for ECS

Configure the ECS service with:

  • VPC

  • Application/private subnets

  • ECS security group

  • Load balancer and target group configuration

The ECS security group should allow application traffic from the ALB security group.

14. Verify the ECS Task

Navigate to:

Code
ECS → Cluster → Service → Tasks

Verify that:

Code
Task Status = RUNNING
Target Group Status = HEALTHY

A healthy target indicates that the load balancer can successfully communicate with the application task.

15. Test the Application Through the ALB

Copy the DNS name provided by the Application Load Balancer.

Open:

Code
http://<ALB-DNS>

The request should reach the ALB and then be forwarded to a healthy ECS task.

For a production deployment, the application should normally be accessed through HTTPS rather than plain HTTP.

16. Create an RDS DB Subnet Group

A DB subnet group tells Amazon RDS which subnets it can use for the database.

Create the DB subnet group using the private database subnets.

Code
RDS
 |
 +-- DB Subnet Group
       |
       +-- Private DB Subnet
       +-- Private DB Subnet

17. Create Amazon RDS

Create the database using Amazon RDS.

The database should use private networking and an RDS security group that allows database traffic only from the ECS security group.

The configuration includes:

Code
RDS
 |
 +-- Private Subnets
 +-- RDS-SG
 +-- Automated Backups
 +-- Backup Retention

The database can be configured as MySQL or PostgreSQL according to the application's requirements.

The database should not be publicly accessible when it is intended to be used only by the application tier.

18. Save the RDS Endpoint

Once the RDS database is created, retrieve its endpoint.

The application uses this endpoint when connecting to the database.

19. Add the Database Connection Configuration to the .NET Application

Configure the database connection information for the ECS task.

For a learning environment, the configuration can be provided through ECS task configuration. For production workloads, sensitive database credentials should preferably be stored in a dedicated secrets-management solution such as AWS Secrets Manager rather than being hard-coded in application code or stored directly in source control.

After changing the configuration, create a new task definition revision and update the ECS service.

20. Validate the Complete Workflow

At this stage, the complete application flow should look like this:

Code
Browser
   |
   | HTTP :80
   v
ALB
   |
   | HTTP :8080
   v
ECS Fargate Container
   |
   | Database Connection
   v
RDS

The image flow is:

Code
Docker Image
     |
     | docker push
     v
ECR
     |
     | Pull Image
     v
ECS Fargate

The logging flow is:

Code
ECS Container
     |
     | Logs
     v
CloudWatch Logs

21. Scale the ECS Service

The ECS service maintains the desired number of running tasks.

For example, if the desired task count is changed from one to two:

Code
Desired Count: 1
       |
       v
ECS Task 1

After increasing the desired count:

Code
Desired Count: 2
       |
       +----> ECS Task 1
       |
       +----> ECS Task 2

ECS starts another Fargate task.

The ALB target group can then distribute requests among the healthy tasks.

This demonstrates horizontal scaling by increasing the desired task count manually.

For a production environment, ECS Service Auto Scaling can be configured to adjust the desired task count automatically based on metrics and scaling policies.

Navigate to:

Code
ECS → Cluster → Service → Tasks

and verify that both tasks are running.

22. Create a CloudWatch Dashboard

CloudWatch provides centralized monitoring instead of requiring each AWS service to be checked separately.

Create a dashboard containing relevant metrics for ECS and RDS.

For ECS:

Code
ECS
 |
 +-- Service Metrics
 |
 +-- Task/Container Metrics

For RDS:

Code
RDS
 |
 +-- CPU
 |
 +-- Connections
 |
 +-- Other Relevant Metrics

23. Create a CloudWatch Alarm

A CloudWatch alarm can monitor a selected metric and trigger an SNS notification when the configured condition is met.

The flow is:

Code
AWS Metric
    |
    v
CloudWatch Alarm
    |
    v
SNS Topic
    |
    v
Email

The alarm threshold should be selected according to the application's actual resource and performance requirements.

24. Enable ECS Container Insights

Container Insights provides additional ECS task and container-level monitoring information.

Enable Container Insights for the ECS environment and use the resulting metrics and information for troubleshooting and monitoring.

25. Verify CloudWatch Logs

Container logs should be centralized in CloudWatch rather than being available only inside the running container.

Navigate to:

Code
CloudWatch
   → Log Groups
   → ECS Log Group

Verify that the ECS application is sending logs successfully.

Moving from Manual Deployment to Infrastructure as Code

The previous steps create the ECS and RDS environment manually.

The same infrastructure can also be represented using AWS CloudFormation.

Instead of configuring each resource manually, CloudFormation allows the infrastructure to be described as code.

CloudFormation Template

1. Create a CloudFormation Template

The CloudFormation template can define the infrastructure required for the application.

The planned resources include:

SQL
CloudFormation
   |
   +-- VPC
   +-- Subnets
   +-- Security Groups
   +-- IAM Roles
   +-- ECR
   +-- ECS Cluster
   +-- ECS Task Definition
   +-- ECS Service
   +-- ALB
   +-- Target Group
   +-- RDS
   +-- CloudWatch

This allows the environment to be recreated consistently instead of configuring every resource manually.

2. Add Parameters

Instead of hard-coding environment-specific values, parameters can be used so that the same CloudFormation template can be reused with different configurations.

Example parameters include:

Code
Parameters
   |
   +-- ECS Task CPU
   +-- ECS Task Memory
   +-- RDS Instance Size

The AWS Region is normally selected as part of the deployment environment rather than being treated as a resource parameter in every template.

Parameters make it easier to customize the infrastructure without changing the core template.

3. Create a Change Set

CloudFormation change sets can be used to review infrastructure changes before applying them.

The basic workflow is:

Code
Create/Update Template
        |
        v
Create Change Set
        |
        v
Review Changes
        |
        v
Deploy

This provides a way to review the proposed infrastructure changes before deployment.

Component Summary

The complete architecture can be summarized as follows.

1. Amazon ECR

The Docker image is stored in ECR.

2. Amazon ECS Fargate

ECS Fargate pulls the image and runs it as a task.

3. Application Load Balancer

The ALB exposes the application through HTTP and forwards requests to healthy ECS tasks.

4. Amazon RDS

The application connects to RDS, which is deployed in private networking and is not publicly accessible.

5. Security

The ALB accepts internet traffic, ECS accepts application traffic from the ALB, and RDS accepts database traffic from ECS.

6. Logging

ECS container logs are sent to CloudWatch.

7. Monitoring

CloudWatch monitors ECS and RDS, while CloudWatch alarms can send notifications through SNS.

8. Scaling

The ECS desired task count can be increased, causing ECS to launch additional Fargate tasks. For production workloads, ECS Service Auto Scaling can automate this process.

9. Infrastructure as Code

CloudFormation can be used to reproduce the infrastructure using a template.

Production Considerations

The project demonstrates the core deployment architecture. A production environment would normally require additional configuration and operational controls.

HTTPS

Configure HTTPS on the Application Load Balancer and use an appropriate TLS certificate rather than exposing the application only through HTTP.

Secrets Management

Store sensitive database credentials and other secrets in a dedicated secrets-management solution instead of hard-coding them in application code or source control.

Least-Privilege IAM

Grant only the permissions required by the ECS task execution role and application task role.

High Availability

Consider deploying resources across multiple Availability Zones where supported and appropriate for the application's availability requirements.

ECS Auto Scaling

Use ECS Service Auto Scaling when the application needs to automatically increase or decrease the number of running tasks based on workload.

Database Backups

Configure RDS backup retention according to the application's recovery requirements and test the recovery process.

Network Access

Keep application and database resources in appropriate private subnets and expose only the components that need to accept internet traffic.

Monitoring and Alerting

Configure CloudWatch dashboards and alarms for application, ECS, ALB, and RDS metrics that matter to the workload.

Health Checks

Configure meaningful application health checks so that the load balancer can stop sending traffic to unhealthy tasks.

Common Troubleshooting Issues

ECS Task Keeps Stopping

Check:

  • CloudWatch container logs

  • ECS task stopped reason

  • CPU and memory configuration

  • Container startup errors

  • IAM permissions

  • ECR image availability

Target Group Shows Unhealthy

Check:

  • Container port

  • Target group port

  • Security group rules

  • Health-check path

  • Application startup status

  • Whether the application is listening on the expected port

ECS Cannot Connect to RDS

Check:

  • RDS security group

  • ECS security group

  • RDS endpoint

  • Database port

  • Database credentials

  • VPC and subnet configuration

  • Database availability

For MySQL, verify the database port is typically 3306.

For PostgreSQL, verify the database port is typically 5432.

Complete Creation Order

The complete deployment can be organized into eight phases.

PHASE 1: Foundation

  1. Create VPC

  2. Create subnets

  3. Create security groups

    • ALB-SG

    • ECS-SG

    • RDS-SG

  4. Create IAM ECS task execution role

  5. Create IAM ECS task role if the application requires AWS service access

  6. Create CloudWatch log group

  7. Create SNS topic and email subscription

PHASE 2: Application Resources

  1. Create ECR repository

  2. Build Docker image

  3. Push Docker image to ECR

  4. Create ECS Fargate cluster

  5. Create ECS task definition

  6. Create Application Load Balancer

  7. Create target group

  8. Configure target group health checks

PHASE 3: Connect the Application

  1. Create ECS service

  2. Connect ECS service to the target group

  3. Connect ALB to the target group

  4. Configure ECS networking and security groups

  5. Start ECS task

  6. Verify target status is healthy

  7. Open the ALB DNS name in a browser

PHASE 4: Database

  1. Create RDS DB subnet group

  2. Create RDS MySQL/PostgreSQL database

  3. Configure private subnets

  4. Configure RDS security group

  5. Configure automated backups

  6. Note the RDS endpoint

PHASE 5: Application to Database

  1. Store/configure the database parameter

  2. Update ECS task configuration

  3. Create a new task definition revision

  4. Update the ECS service

  5. Verify application-to-RDS connectivity

PHASE 6: Scaling

  1. Change the ECS desired task count

  2. Verify ECS launches an additional task

  3. Verify both tasks are running

  4. Verify the ALB distributes traffic between healthy tasks

  5. Configure ECS Service Auto Scaling when automatic scaling is required

PHASE 7: Monitoring

  1. Create CloudWatch dashboard

  2. Add ECS metrics

  3. Add RDS metrics

  4. Create CloudWatch alarm

  5. Configure SNS notification

  6. Enable ECS Container Insights

  7. Verify centralized CloudWatch logs

PHASE 8: CloudFormation

  1. Create CloudFormation template

  2. Define VPC and network resources

  3. Define security groups

  4. Define IAM roles

  5. Define ECR

  6. Define ECS resources

  7. Define ALB

  8. Define RDS

  9. Add parameters

  10. Create a change set

  11. Review the proposed changes

  12. Deploy the stack

  13. Verify the deployed resources

Key Learnings

This project helped me understand how a traditional .NET application can be transformed into a containerized and monitored cloud application using AWS managed services.

The most important learning was not just how to create individual AWS resources, but how those resources fit together.

The application uses:

Code
Internet
   |
   v
Application Load Balancer
   |
   v
ECS Fargate
   |
   v
Amazon RDS

while supporting services handle the surrounding infrastructure:

SQL
ECR
 |
 +-- Stores container image

CloudWatch
 |
 +-- Logs
 +-- Metrics
 +-- Dashboards
 +-- Alarms

SNS
 |
 +-- Notifications

CloudFormation
 |
 +-- Infrastructure as Code

This deployment provides hands-on understanding of networking, security groups, containerization, load balancing, databases, monitoring, scaling, and Infrastructure as Code in a single .NET application architecture.

Technologies Used

  • C#

  • .NET

  • Docker

  • Amazon ECS Fargate

  • Amazon ECR

  • Application Load Balancer

  • Amazon RDS

  • Amazon VPC

  • Amazon CloudWatch

  • Amazon SNS

  • ECS Container Insights

  • AWS CloudFormation