Skip to content

Commit 2f2a5b6

Browse files
committed
chore: remove .terraform.lock.hcl and clean ignored artifacts
1 parent 5a65ce6 commit 2f2a5b6

11 files changed

Lines changed: 459 additions & 450 deletions

File tree

infra/backend.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Remote state in S3 with DynamoDB state locking
2+
terraform {
3+
backend "s3" {
4+
bucket = "docker-ecs-deployment" # S3 bucket for tfstate
5+
key = "ecs-demo/infra.tfstate" # Key (path) inside the bucket
6+
region = "us-east-1" # Bucket region
7+
dynamodb_table = "docker-ecs-deployment" # Table for state locking
8+
encrypt = true # Server-side encryption for state
9+
}
10+
}

infra/ecr.tf

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# infra/ecr.tf
2+
#############################################
3+
# ECR (repo + lifecycle policy)
4+
#############################################
5+
6+
resource "aws_ecr_repository" "this" {
7+
name = var.ecr_repo_name
8+
image_tag_mutability = "MUTABLE" # allow retagging 'latest'
9+
force_delete = true # destroy even if images remain
10+
11+
image_scanning_configuration { scan_on_push = true }
12+
encryption_configuration { encryption_type = "AES256" }
13+
14+
tags = { Project = var.project_name }
15+
}
16+
17+
# Keep it clean: expire untagged, trim 'latest' images
18+
resource "aws_ecr_lifecycle_policy" "this" {
19+
repository = aws_ecr_repository.this.name
20+
policy = jsonencode({
21+
rules = [
22+
{
23+
rulePriority = 1,
24+
description = "Expire untagged after 7 days",
25+
selection = {
26+
tagStatus = "untagged",
27+
countType = "sinceImagePushed",
28+
countUnit = "days",
29+
countNumber = 7
30+
},
31+
action = { type = "expire" }
32+
},
33+
{
34+
rulePriority = 2,
35+
description = "Keep last 10 'latest' images",
36+
selection = {
37+
tagStatus = "tagged",
38+
tagPrefixList = ["latest"],
39+
countType = "imageCountMoreThan",
40+
countNumber = 10
41+
},
42+
action = { type = "expire" }
43+
}
44+
]
45+
})
46+
}

infra/ecs.tf

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# infra/ecs.tf
2+
#############################################
3+
# ECS Cluster, Roles, Task Definition, Service
4+
#############################################
5+
6+
# Plain ECS cluster
7+
resource "aws_ecs_cluster" "this" {
8+
name = "${var.project_name}-cluster"
9+
}
10+
11+
# Execution role: ECS agent needs this to pull from ECR, write logs
12+
resource "aws_iam_role" "ecs_execution_role" {
13+
name = "${var.project_name}-ecs-exec-role"
14+
assume_role_policy = jsonencode({
15+
Version = "2012-10-17",
16+
Statement = [{
17+
Effect = "Allow",
18+
Principal = { Service = "ecs-tasks.amazonaws.com" },
19+
Action = "sts:AssumeRole"
20+
}]
21+
})
22+
tags = { Project = var.project_name }
23+
}
24+
25+
# Attach AWS-managed policy for ECS execution
26+
resource "aws_iam_role_policy_attachment" "ecs_exec_policy" {
27+
role = aws_iam_role.ecs_execution_role.name
28+
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
29+
}
30+
31+
# Task role (app’s own AWS permissions). Empty by default.
32+
resource "aws_iam_role" "ecs_task_role" {
33+
name = "${var.project_name}-ecs-task-role"
34+
assume_role_policy = aws_iam_role.ecs_execution_role.assume_role_policy
35+
tags = { Project = var.project_name }
36+
}
37+
38+
# Fargate task definition (ARM64 to save cost on Graviton)
39+
resource "aws_ecs_task_definition" "app" {
40+
family = "${var.project_name}-task"
41+
requires_compatibilities = ["FARGATE"]
42+
network_mode = "awsvpc"
43+
cpu = var.task_cpu
44+
memory = var.task_memory
45+
execution_role_arn = aws_iam_role.ecs_execution_role.arn
46+
task_role_arn = aws_iam_role.ecs_task_role.arn
47+
48+
# Single container: pulls :latest tag from ECR repo
49+
container_definitions = jsonencode([
50+
{
51+
name = "app",
52+
image = "${aws_ecr_repository.this.repository_url}:latest",
53+
essential = true,
54+
portMappings = [{
55+
containerPort = var.app_port,
56+
hostPort = var.app_port,
57+
protocol = "tcp"
58+
}],
59+
logConfiguration = {
60+
logDriver = "awslogs",
61+
options = {
62+
awslogs-group = aws_cloudwatch_log_group.app.name,
63+
awslogs-region = var.region,
64+
awslogs-stream-prefix = "ecs"
65+
}
66+
}
67+
}
68+
])
69+
70+
runtime_platform {
71+
operating_system_family = "LINUX"
72+
cpu_architecture = "ARM64" # Graviton2/3 (cheaper)
73+
}
74+
75+
tags = { Project = var.project_name }
76+
}
77+
78+
# ECS service on Fargate with public IP (no ALB; connect directly to task ENI)
79+
resource "aws_ecs_service" "app" {
80+
name = "${var.project_name}-svc"
81+
cluster = aws_ecs_cluster.this.id
82+
task_definition = aws_ecs_task_definition.app.arn
83+
desired_count = var.desired_count # 0 by default (idle)
84+
launch_type = "FARGATE"
85+
propagate_tags = "SERVICE"
86+
87+
network_configuration {
88+
subnets = module.vpc.public_subnets
89+
security_groups = [aws_security_group.service.id]
90+
assign_public_ip = true # attach public IP to task ENI
91+
}
92+
93+
# Safer rolling update with circuit breaker auto-rollback
94+
deployment_circuit_breaker {
95+
enable = true
96+
rollback = true
97+
}
98+
99+
# Don’t recreate service on each TD revision; we update explicitly
100+
lifecycle {
101+
ignore_changes = [task_definition]
102+
}
103+
104+
tags = { Project = var.project_name }
105+
}

infra/locals.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
############################################
2+
# Local paths & hashes for Lambda packages
3+
############################################
4+
locals {
5+
wake_zip_path = "${path.module}/wake.zip"
6+
wake_zip_hash = try(filebase64sha256(local.wake_zip_path), "")
7+
8+
sleep_zip_path = "${path.module}/sleep.zip"
9+
sleep_zip_hash = try(filebase64sha256(local.sleep_zip_path), "")
10+
}

infra/logs.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# infra/logs.tf
2+
#############################################
3+
# CloudWatch Logs for ECS tasks
4+
#############################################
5+
6+
resource "aws_cloudwatch_log_group" "app" {
7+
name = "/ecs/${var.project_name}"
8+
retention_in_days = 3 # short retention to save cost
9+
tags = { Project = var.project_name }
10+
}

0 commit comments

Comments
 (0)