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:
Browser
|
| HTTP :80
v
Application Load Balancer
|
| HTTP :8080
v
ECS Fargate
|
| Database connection
v
Amazon RDSThe 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:
Inbound:
Protocol: HTTP
Port: 80
Source: 0.0.0.0/0ECS-SG
The ECS security group controls traffic going to the application containers.
Inbound:
Protocol: TCP
Port: 8080
Source: ALB-SGThis 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:
Inbound:
Protocol: TCP
Port: 3306
Source: ECS-SGFor PostgreSQL:
Inbound:
Protocol: TCP
Port: 5432
Source: ECS-SGThe overall request flow is:
Internet
|
| HTTP :80
v
ALB
|
| TCP :8080
v
ECS
|
| DB Port
v
RDSThe 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.
ECS/Fargate
|
+----> ECR
| Pull Docker image
|
+----> CloudWatch
Send container logsECS 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:
/aws/ecs/my-applicationCentralized 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:
aws-assignment-alertsThe notification flow is:
CloudWatch Alarm
|
v
SNS
|
v
Email7. 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.
Local Machine
|
| docker build
v
Docker Image
|
| docker push
v
Amazon ECRECR 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:
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.
Internet
|
| HTTP :80
v
Application Load BalancerFor 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:
ALB
|
| HTTP
v
Target Group
|
| Port 8080
v
ECS TasksThe 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:
Protocol: HTTP
Port: 8080
Health Check Path: /healthThe 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:
ECS Cluster
|
v
Task Definition
|
v
Fargate Service
|
v
Desired Task CountNavigate 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:
ECS → Cluster → Service → TasksVerify that:
Task Status = RUNNING
Target Group Status = HEALTHYA 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:
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.
RDS
|
+-- DB Subnet Group
|
+-- Private DB Subnet
+-- Private DB Subnet17. 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:
RDS
|
+-- Private Subnets
+-- RDS-SG
+-- Automated Backups
+-- Backup RetentionThe 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:
Browser
|
| HTTP :80
v
ALB
|
| HTTP :8080
v
ECS Fargate Container
|
| Database Connection
v
RDSThe image flow is:
Docker Image
|
| docker push
v
ECR
|
| Pull Image
v
ECS FargateThe logging flow is:
ECS Container
|
| Logs
v
CloudWatch Logs21. 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:
Desired Count: 1
|
v
ECS Task 1After increasing the desired count:
Desired Count: 2
|
+----> ECS Task 1
|
+----> ECS Task 2ECS 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:
ECS → Cluster → Service → Tasksand 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:
ECS
|
+-- Service Metrics
|
+-- Task/Container MetricsFor RDS:
RDS
|
+-- CPU
|
+-- Connections
|
+-- Other Relevant Metrics23. 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:
AWS Metric
|
v
CloudWatch Alarm
|
v
SNS Topic
|
v
EmailThe 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:
CloudWatch
→ Log Groups
→ ECS Log GroupVerify 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:
CloudFormation
|
+-- VPC
+-- Subnets
+-- Security Groups
+-- IAM Roles
+-- ECR
+-- ECS Cluster
+-- ECS Task Definition
+-- ECS Service
+-- ALB
+-- Target Group
+-- RDS
+-- CloudWatchThis 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:
Parameters
|
+-- ECS Task CPU
+-- ECS Task Memory
+-- RDS Instance SizeThe 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:
Create/Update Template
|
v
Create Change Set
|
v
Review Changes
|
v
DeployThis 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
Create VPC
Create subnets
Create security groups
ALB-SG
ECS-SG
RDS-SG
Create IAM ECS task execution role
Create IAM ECS task role if the application requires AWS service access
Create CloudWatch log group
Create SNS topic and email subscription
PHASE 2: Application Resources
Create ECR repository
Build Docker image
Push Docker image to ECR
Create ECS Fargate cluster
Create ECS task definition
Create Application Load Balancer
Create target group
Configure target group health checks
PHASE 3: Connect the Application
Create ECS service
Connect ECS service to the target group
Connect ALB to the target group
Configure ECS networking and security groups
Start ECS task
Verify target status is healthy
Open the ALB DNS name in a browser
PHASE 4: Database
Create RDS DB subnet group
Create RDS MySQL/PostgreSQL database
Configure private subnets
Configure RDS security group
Configure automated backups
Note the RDS endpoint
PHASE 5: Application to Database
Store/configure the database parameter
Update ECS task configuration
Create a new task definition revision
Update the ECS service
Verify application-to-RDS connectivity
PHASE 6: Scaling
Change the ECS desired task count
Verify ECS launches an additional task
Verify both tasks are running
Verify the ALB distributes traffic between healthy tasks
Configure ECS Service Auto Scaling when automatic scaling is required
PHASE 7: Monitoring
Create CloudWatch dashboard
Add ECS metrics
Add RDS metrics
Create CloudWatch alarm
Configure SNS notification
Enable ECS Container Insights
Verify centralized CloudWatch logs
PHASE 8: CloudFormation
Create CloudFormation template
Define VPC and network resources
Define security groups
Define IAM roles
Define ECR
Define ECS resources
Define ALB
Define RDS
Add parameters
Create a change set
Review the proposed changes
Deploy the stack
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:
Internet
|
v
Application Load Balancer
|
v
ECS Fargate
|
v
Amazon RDSwhile supporting services handle the surrounding infrastructure:
ECR
|
+-- Stores container image
CloudWatch
|
+-- Logs
+-- Metrics
+-- Dashboards
+-- Alarms
SNS
|
+-- Notifications
CloudFormation
|
+-- Infrastructure as CodeThis 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


Join the conversation! Your thoughts help the community grow.