AWS WAF Web Application Firewall with Terraform
Protect your applications with AWS WAF rules managed by Terraform — rate limiting, IP blocking, and SQL injection prevention.
Cloud Computing
Deploy containerized applications on AWS ECS Fargate using Terraform with ALB, auto-scaling, and CloudWatch monitoring. Step-by-step guide with code examples...
AWS ECS Fargate removes the need to manage EC2 instances for your containers. You define what to run, and AWS handles the underlying infrastructure. This guide shows how to deploy a complete ECS Fargate setup with Terraform, including networking, load balancing, auto-scaling, and monitoring.
The setup includes:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "ecs-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}resource "aws_ecs_cluster" "main" {
name = "production-cluster"
setting {
name = "containerInsights"
value = "enabled"
}
configuration {
execute_command_configuration {
logging = "OVERRIDE"
log_configuration {
cloud_watch_log_group_name = aws_cloudwatch_log_group.ecs.name
}
}
}
}
resource "aws_ecs_cluster_capacity_providers" "main" {
cluster_name = aws_ecs_cluster.main.name
capacity_providers = ["FARGATE", "FARGATE_SPOT"]
default_capacity_provider_strategy {
capacity_provider = "FARGATE"
weight = 1
base = 1
}
default_capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
weight = 4
}
}resource "aws_ecs_task_definition" "app" {
family = "my-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = 512
memory = 1024
execution_role_arn = aws_iam_role.ecs_execution.arn
task_role_arn = aws_iam_role.ecs_task.arn
container_definitions = jsonencode([
{
name = "app"
image = "${aws_ecr_repository.app.repository_url}:latest"
portMappings = [
{
containerPort = 8080
protocol = "tcp"
}
]
environment = [
{ name = "PORT", value = "8080" },
{ name = "ENV", value = "production" }
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.app.name
"awslogs-region" = var.region
"awslogs-stream-prefix" = "app"
}
}
healthCheck = {
command = ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
interval = 30
timeout = 5
retries = 3
startPeriod = 60
}
}
])
}resource "aws_lb" "main" {
name = "ecs-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = module.vpc.public_subnets
enable_deletion_protection = true
}
resource "aws_lb_target_group" "app" {
name = "app-tg"
port = 8080
protocol = "HTTP"
target_type = "ip"
vpc_id = module.vpc.vpc_id
health_check {
healthy_threshold = 2
unhealthy_threshold = 10
timeout = 10
interval = 15
path = "/health"
matcher = "200"
}
deregistration_delay = 30
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = var.certificate_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.app.arn
}
}resource "aws_ecs_service" "app" {
name = "app-service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = 2
launch_type = "FARGATE"
network_configuration {
subnets = module.vpc.private_subnets
security_groups = [aws_security_group.ecs.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "app"
container_port = 8080
}
deployment_circuit_breaker {
enable = true
rollback = true
}
lifecycle {
ignore_changes = [desired_count]
}
}
resource "aws_appautoscaling_target" "ecs" {
max_capacity = 10
min_capacity = 2
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.app.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_policy" "cpu" {
name = "cpu-scaling"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.ecs.resource_id
scalable_dimension = aws_appautoscaling_target.ecs.scalable_dimension
service_namespace = aws_appautoscaling_target.ecs.service_namespace
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 70
scale_in_cooldown = 300
scale_out_cooldown = 60
}
}resource "aws_security_group" "alb" {
name = "alb-sg"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 443
to_port = 443
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" {
name = "ecs-sg"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}:latest in productionLearn by doing with interactive courses on CopyPasteLearn:
ECS Fargate with Terraform gives you a fully managed container platform with infrastructure as code. The combination of ALB, auto-scaling, and CloudWatch provides a production-grade setup that scales automatically and recovers from failures.
Protect your applications with AWS WAF rules managed by Terraform — rate limiting, IP blocking, and SQL injection prevention.
Manage secrets securely with AWS Secrets Manager and Terraform — rotation, replication, and application integration. Step-by-step guide with code examples an...
Set up a production Redis cluster on AWS ElastiCache with replication, encryption, and automatic failover using Terraform.
Create and configure DynamoDB tables with Terraform including GSIs, auto-scaling, TTL, and point-in-time recovery. Step-by-step guide with code examples and ...