MoinMoin Logo
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Load
    • Save
  • Login

Navigation

  • Start
  • Sitemap
Unknown action login.
  • terraform

Contents

  1. terraform
    1. main.tf for ECS with cherrypy in ECS and postgres in RDS

terraform

Terraform is as open source tool to create, change and manage infrastructure through code (IaC infrastructure as code).

It acts as a infrastructure blueprint.

main.tf for ECS with cherrypy in ECS and postgres in RDS

It sets a public IP for the ECS service and tasks.Using the assign_public_ip=true .

The RDS DB uses publicly_accessible = false which makes it inaccessible publicly.

Other used services:

  • VPC
  • ECR
  • IAM
  • CloudWatch logs

  • SecurityGroups

   1 # Provider definition
   2 terraform {
   3   required_providers {
   4     aws = {
   5       source  = "hashicorp/aws"
   6       version = "~> 5.0"
   7     }
   8   }
   9 }
  10 
  11 provider "aws" {
  12   region = var.aws_region
  13 }
  14 
  15 # Variables
  16 variable "aws_region" {
  17   type    = string
  18   default = "us-east-1"
  19 }
  20 
  21 variable "db_password" {
  22   type        = string
  23   description = "PostgreSQL database master password"
  24   sensitive   = true
  25   default     = "SuperSecurePassword123!"
  26 }
  27 
  28 # --- NETWORKING (VPC) ---
  29 data "aws_availability_zones" "available" {
  30   state = "available"
  31 }
  32 
  33 resource "aws_vpc" "main" {
  34   cidr_block           = "10.0.0.0/16"
  35   enable_dns_hostnames = true
  36   enable_dns_support   = true
  37   tags = { Name = "cherrypy-ecs-vpc" }
  38 }
  39 
  40 resource "aws_subnet" "public_1" {
  41   vpc_id            = aws_vpc.main.id
  42   cidr_block        = "10.0.1.0/24"
  43   availability_zone = data.aws_availability_zones.available.names[0]
  44   map_public_ip_on_launch = true
  45   tags = { Name = "cherrypy-public-1" }
  46 }
  47 
  48 resource "aws_subnet" "public_2" {
  49   vpc_id            = aws_vpc.main.id
  50   cidr_block        = "10.0.2.0/24"
  51   availability_zone = data.aws_availability_zones.available.names[1]
  52   map_public_ip_on_launch = true
  53   tags = { Name = "cherrypy-public-2" }
  54 }
  55 
  56 resource "aws_internet_gateway" "gw" {
  57   vpc_id = aws_vpc.main.id
  58   tags   = { Name = "cherrypy-igw" }
  59 }
  60 
  61 resource "aws_route_table" "public" {
  62   vpc_id = aws_vpc.main.id
  63   route {
  64     cidr_block = "0.0.0.0/0"
  65     gateway_id = aws_internet_gateway.gw.id
  66   }
  67   tags = { Name = "cherrypy-public-rt" }
  68 }
  69 
  70 resource "aws_route_table_association" "public_1" {
  71   subnet_id      = aws_subnet.public_1.id
  72   route_table_id = aws_route_table.public.id
  73 }
  74 
  75 resource "aws_route_table_association" "public_2" {
  76   subnet_id      = aws_subnet.public_2.id
  77   route_table_id = aws_route_table.public.id
  78 }
  79 
  80 # --- SECURITY GROUPS ---
  81 resource "aws_security_group" "ecs_tasks" {
  82   name        = "cherrypy-ecs-tasks-sg"
  83   description = "Allow inbound traffic on port 8080"
  84   vpc_id      = aws_vpc.main.id
  85 
  86   ingress {
  87     protocol    = "tcp"
  88     from_port   = 8080
  89     to_port     = 8080
  90     cidr_blocks = ["0.0.0.0/0"] # For testing. In production, restrict via a Load Balancer.
  91   }
  92 
  93   egress {
  94     protocol    = "-1"
  95     from_port   = 0
  96     to_port     = 0
  97     cidr_blocks = ["0.0.0.0/0"]
  98   }
  99 }
 100 
 101 resource "aws_security_group" "db" {
 102   name        = "cherrypy-db-sg"
 103   description = "Allow inbound traffic from ECS tasks only"
 104   vpc_id      = aws_vpc.main.id
 105 
 106   ingress {
 107     protocol        = "tcp"
 108     from_port       = 5432
 109     to_port         = 5432
 110     security_groups = [aws_security_group.ecs_tasks.id]
 111   }
 112 
 113   egress {
 114     protocol    = "-1"
 115     from_port   = 0
 116     to_port     = 0
 117     cidr_blocks = ["0.0.0.0/0"]
 118   }
 119 }
 120 
 121 # --- DATABASE (RDS PostgreSQL) ---
 122 resource "aws_db_subnet_group" "main" {
 123   name       = "cherrypy-db-subnet-group"
 124   subnet_ids = [aws_subnet.public_1.id, aws_subnet.public_2.id]
 125 }
 126 
 127 resource "aws_db_instance" "postgres" {
 128   identifier             = "cherrypy-postgres-db"
 129   allocated_storage      = 20
 130   engine                 = "postgres"
 131   engine_version         = "15"
 132   instance_class         = "db.t4g.micro"
 133   db_name                = "cherrypy_db"
 134   username               = "cherrypy_user"
 135   password               = var.db_password
 136   db_subnet_group_name   = aws_db_subnet_group.main.name
 137   vpc_security_group_ids = [aws_security_group.db.id]
 138   skip_final_snapshot    = true
 139 }
 140 
 141 # --- CONTAINER REGISTRY (ECR) ---
 142 resource "aws_ecr_repository" "app" {
 143   name                 = "cherrypy-app"
 144   image_tag_mutability = "MUTABLE"
 145   image_scanning_configuration {
 146     scan_on_push = true
 147   }
 148 }
 149 
 150 # --- IAM ROLES FOR ECS ---
 151 resource "aws_iam_role" "ecs_execution_role" {
 152   name = "cherrypy-ecs-execution-role"
 153 
 154   assume_role_policy = jsonencode({
 155     Version = "2012-10-17"
 156     Statement = [{
 157       Action = "sts:AssumeRole"
 158       Effect = "Allow"
 159       Principal = { Service = "ecs-tasks.amazonaws.com" }
 160     }]
 161   })
 162 }
 163 
 164 resource "aws_iam_role_policy_attachment" "ecs_execution" {
 165   role       = aws_iam_role.ecs_execution_role.name
 166   policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
 167 }
 168 
 169 # --- CONTAINER ORCHESTRATION (ECS) ---
 170 resource "aws_ecs_cluster" "main" {
 171   name = "cherrypy-ecs-cluster"
 172 }
 173 
 174 resource "aws_ecs_task_definition" "app" {
 175   family                   = "cherrypy-task"
 176   network_mode             = "awsvpc"
 177   requires_compatibilities = ["FARGATE"]
 178   cpu                      = "256"
 179   memory                   = "512"
 180   execution_role_arn       = aws_iam_role.ecs_execution_role.arn
 181 
 182   container_definitions = jsonencode([{
 183     name      = "cherrypy-container"
 184     image     = "${aws_ecr_repository.app.repository_url}:latest"
 185     essential = true
 186     portMappings = [{
 187       containerPort = 8080
 188       hostPort      = 8080
 189     }]
 190     environment = [
 191       { name = "DB_HOST", value = aws_db_instance.postgres.address },
 192       { name = "DB_NAME", value = aws_db_instance.postgres.db_name },
 193       { name = "DB_USER", value = aws_db_instance.postgres.username },
 194       { name = "DB_PASS", value = var.db_password }
 195     ]
 196   }])
 197 }
 198 
 199 resource "aws_ecs_service" "main" {
 200   name            = "cherrypy-service"
 201   cluster         = aws_ecs_cluster.main.id
 202   task_definition = aws_ecs_task_definition.app.arn
 203   desired_count   = 1
 204   launch_type     = "FARGATE"
 205 
 206   network_configuration {
 207     subnets          = [aws_subnet.public_1.id, aws_subnet.public_2.id]
 208     security_groups  = [aws_security_group.ecs_tasks.id]
 209     assign_public_ip = true
 210   }
 211 }
 212 
 213 # --- OUTPUTS ---
 214 output "ecr_repository_url" {
 215   value       = aws_ecr_repository.app.repository_url
 216   description = "Use URL to push the CherryPy Docker image"
 217 }
 218 
 219 output "db_endpoint" {
 220   value       = aws_db_instance.postgres.endpoint
 221   description = "PostgreSQL database endpoint"
 222 }

   1 sudo apk add aws-cli --repository=https://alpinelinux.org
   2 aws --version
   3 aws configure
   4 sudo apk add terraform --repository=https://alpinelinux.org
   5 terraform --version
   6 terraform init
   7 terraform validate 
   8 terraform plan 
   9 terraform applu 
  10 aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ://amazonaws.com
  11 docker build -t cherrypy-app .
  12 docker tag cherrypy-app:latest ://amazonaws.com
  13 docker push ://amazonaws.com
  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01