Terraform Deployment Guide: ECS Fargate with VPC, ALB, ECR, and CodeBuild Integration


✅ Prerequisites
Before running the Terraform script, make sure the following are ready:
1. Install Terraform
Download and install Terraform from the official website.
2. Set Up AWS Credentials
Ensure AWS credentials are configured using either:
Environment variables:
AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
AWS CLI config:
~/.aws/credentials
🔧 Running the Terraform Script
1. Initialize Terraform
terraform init
2. Review the Plan
terraform plan
3. Apply the Configuration
terraform apply
Type yes
to confirm the execution.
4. Verify Resources
Check the AWS Console to ensure that resources like VPC, ECS cluster, ALB, and services are up and running.
5. (Optional) Destroy Resources
terraform destroy
🛠️ Build & Push Docker Image (Optional Step)
Use AWS CodeBuild to build and push your Docker image to ECR before running this Terraform script.
⚠️ Important: Make sure the ECR repository name in your CodeBuild pipeline matches the one defined in your Terraform script.
🧱 Terraform Code
# Provider
provider "aws" {
region = "us-east-1"
}
# VPC
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
}
# Subnets
resource "aws_subnet" "public_subnet_1" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true
}
resource "aws_subnet" "public_subnet_2" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.3.0/24"
availability_zone = "us-east-1b"
map_public_ip_on_launch = true
}
resource "aws_subnet" "private_subnet_1" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1a"
}
resource "aws_subnet" "private_subnet_2" {
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.4.0/24"
availability_zone = "us-east-1b"
}
# Internet Gateway and NAT
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.my_vpc.id
}
resource "aws_eip" "nat_eip" {
domain = "vpc"
}
resource "aws_nat_gateway" "nat_gateway" {
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.public_subnet_1.id
}
# Route Tables
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
resource "aws_route_table" "private_rt" {
vpc_id = aws_vpc.my_vpc.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_gateway.id
}
}
# Route Table Associations
resource "aws_route_table_association" "public_association_1" {
subnet_id = aws_subnet.public_subnet_1.id
route_table_id = aws_route_table.public_rt.id
}
resource "aws_route_table_association" "public_association_2" {
subnet_id = aws_subnet.public_subnet_2.id
route_table_id = aws_route_table.public_rt.id
}
resource "aws_route_table_association" "private_association_1" {
subnet_id = aws_subnet.private_subnet_1.id
route_table_id = aws_route_table.private_rt.id
}
resource "aws_route_table_association" "private_association_2" {
subnet_id = aws_subnet.private_subnet_2.id
route_table_id = aws_route_table.private_rt.id
}
# ECS Cluster
resource "aws_ecs_cluster" "ecs_cluster" {
name = "my-ecs-cluster"
}
# ECR Repository
resource "aws_ecr_repository" "app_ecr" {
name = "my-app-repo"
}
# IAM Role for ECS Task Execution
data "aws_iam_role" "ecs_task_execution_role" {
name = "ecsTaskExecutionRole"
}
resource "aws_iam_role_policy_attachment" "ecs_task_execution_policy" {
role = data.aws_iam_role.ecs_task_execution_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
# CloudWatch Log Group
resource "aws_cloudwatch_log_group" "app_logs" {
name = "my-app-log-group"
retention_in_days = 7
tags = {
Name = "my-app-log-group"
}
}
# ECS Task Definition
resource "aws_ecs_task_definition" "app_task" {
family = "my-ecs-task"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = "256"
memory = "512"
execution_role_arn = data.aws_iam_role.ecs_task_execution_role.arn
container_definitions = jsonencode([
{
name = "my-app-container"
image = "${aws_ecr_repository.app_ecr.repository_url}:latest"
essential = true
portMappings = [
{
containerPort = 8000
hostPort = 8000
protocol = "tcp"
}
]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.app_logs.name
awslogs-region = "us-east-1"
awslogs-stream-prefix = "ecs"
}
}
}
])
}
# Security Groups
resource "aws_security_group" "alb_sg" {
name = "alb-sg"
description = "Allow HTTP traffic from the internet"
vpc_id = aws_vpc.my_vpc.id
ingress {
from_port = 8000
to_port = 8000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group" "ecs_security_group" {
name = "ecs-sg"
description = "Allow traffic to ECS containers"
vpc_id = aws_vpc.my_vpc.id
ingress {
from_port = 8000
to_port = 8000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Load Balancer and Listener
resource "aws_lb" "app_alb" {
name = "app-alb"
internal = false
load_balancer_type = "application"
subnets = [aws_subnet.public_subnet_1.id, aws_subnet.public_subnet_2.id]
security_groups = [aws_security_group.alb_sg.id]
}
resource "aws_lb_target_group" "app_tg" {
name = "app-target-group"
port = 8000
protocol = "HTTP"
vpc_id = aws_vpc.my_vpc.id
target_type = "ip"
health_check {
path = "/"
interval = 30
timeout = 5
healthy_threshold = 3
unhealthy_threshold = 3
}
}
resource "aws_lb_listener" "app_listener" {
load_balancer_arn = aws_lb.app_alb.arn
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app_tg.arn
}
}
# ECS Service
resource "aws_ecs_service" "ecs_service" {
name = "my-app-service"
cluster = aws_ecs_cluster.ecs_cluster.id
task_definition = aws_ecs_task_definition.app_task.arn
desired_count = 2
launch_type = "FARGATE"
network_configuration {
subnets = [aws_subnet.private_subnet_1.id]
security_groups = [aws_security_group.ecs_security_group.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.app_tg.arn
container_name = "my-app-container"
container_port = 8000
}
depends_on = [
aws_lb.app_alb,
aws_lb_target_group.app_tg,
aws_lb_listener.app_listener
]
}
# CloudWatch Alarms (Optional - add SNS topic ARN if needed)
resource "aws_cloudwatch_metric_alarm" "cpu_utilization_alarm" {
alarm_name = "HighCPUUtilization"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "CPUUtilization"
namespace = "AWS/ECS"
period = 300
statistic = "Average"
threshold = 70
alarm_description = "Alarm when CPU exceeds 70%"
dimensions = {
ServiceName = aws_ecs_service.ecs_service.name
ClusterName = aws_ecs_cluster.ecs_cluster.name
}
}
resource "aws_cloudwatch_metric_alarm" "ecs_service_failure_alarm" {
alarm_name = "ECSServiceFailure"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name = "ServiceFailures"
namespace = "AWS/ECS"
period = 300
statistic = "Sum"
threshold = 0
alarm_description = "Alarm when ECS service fails"
dimensions = {
ServiceName = aws_ecs_service.ecs_service.name
ClusterName = aws_ecs_cluster.ecs_cluster.name
}
}
# Output
output "load_balancer_url" {
value = aws_lb.app_alb.dns_name
}
Subscribe to my newsletter
Read articles from Ankur Dev directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ankur Dev
Ankur Dev
AWS Cloud Expertise : Skilled in EC2, S3, Lambda, CloudFormation, and more to architect, deploy, and manage cloud solutions. Infrastructure as Code (IaC) : Automating cloud infrastructure using Terraform and CloudFormation for consistency and scalability. CI/CD Pipelines : Designing and managing efficient, automated continuous integration and deployment pipelines for faster releases. Containerization & Orchestration : Leveraging Docker and Kubernetes for containerized applications and seamless orchestration. Serverless Architectures : Implementing serverless solutions using AWS Lambda to reduce overhead and enhance scalability. Cloud Security : Ensuring robust security practices and compliance in cloud environments to protect sensitive data. Scripting & Automation : Writing efficient scripts in Python and Bash to automate manual tasks and improve workflow. Monitoring & Logging : Utilizing AWS CloudWatch, ELK Stack, and other tools to monitor and analyze system performance in real-time. Performance Optimization : Focused on optimizing cloud resources to improve speed, scalability, and cost-efficiency.