Elastic Container Service - amresh087/newronaRepos GitHub Wiki

Elastic Container Service

Screenshot 2026-05-13 at 1 03 34 PM

1. Dockerfile

File name : app/Dockerfile

      FROM eclipse-temurin:17
      COPY target/loan-service.jar app.jar
      ENTRYPOINT ["java","-jar","app.jar"]

Explanation:

  • Uses Java 17
  • Copies Spring Boot jar
  • Runs app on port 8080

2. application.yml

File name : app/Dockerfile

      server:
        port: 8080

      spring:
        datasource:
          url: jdbc:postgresql://rds-url:5432/loan_db
          username: admin
          password: password

      management:
        endpoints:
          web:
            exposure:
              include: health

2. provider.tf

      provider "aws" {
        region = "ap-south-1"
      }

Explanation:

  • AWS region configuration

3. variables.tf

      variable "app_name" {
        default = "springboot-ecs"
      }

      variable "container_port" {
        default = 8080
      }

Explanation:

  • Reusable variables

4. vpc.tf

      resource "aws_vpc" "main" {
        cidr_block = "10.0.0.0/16"
      }

      resource "aws_subnet" "subnet1" {
        vpc_id                  = aws_vpc.main.id
        cidr_block              = "10.0.1.0/24"
        availability_zone       = "ap-south-1a"
        map_public_ip_on_launch = true
      }

      resource "aws_subnet" "subnet2" {
        vpc_id                  = aws_vpc.main.id
        cidr_block              = "10.0.2.0/24"
        availability_zone       = "ap-south-1b"
        map_public_ip_on_launch = true
      }

      resource "aws_internet_gateway" "igw" {
        vpc_id = aws_vpc.main.id
      }

      resource "aws_route_table" "rt" {
        vpc_id = aws_vpc.main.id
      }

      resource "aws_route" "internet_access" {
        route_table_id         = aws_route_table.rt.id
        destination_cidr_block = "0.0.0.0/0"
        gateway_id             = aws_internet_gateway.igw.id
      }
      resource "aws_route_table_association" "a1" {
        subnet_id      = aws_subnet.subnet1.id
        route_table_id = aws_route_table.rt.id
      }

      resource "aws_route_table_association" "a2" {
        subnet_id      = aws_subnet.subnet2.id
        route_table_id = aws_route_table.rt.id
      }

Explanation:

  • Creates VPC
  • Creates 2 public subnets
  • Internet access enabled

5. security-group.tf

      resource "aws_security_group" "alb_sg" {
        vpc_id = aws_vpc.main.id

        ingress {
          from_port   = 80
          to_port     = 80
          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_sg" {
        vpc_id = aws_vpc.main.id

        ingress {
          from_port       = 8080
          to_port         = 8080
          protocol        = "tcp"
          security_groups = [aws_security_group.alb_sg.id]
        }
      egress {
          from_port   = 0
          to_port     = 0
          protocol    = "-1"
          cidr_blocks = ["0.0.0.0/0"]
        }
      }

Explanation:

  • ALB accepts internet traffic
  • ECS accepts only ALB traffic

6. iam.tf

      resource "aws_iam_role" "ecs_task_execution_role" {
        name = "ecsTaskExecutionRole"

        assume_role_policy = jsonencode({
          Version = "2012-10-17"
          Statement = [{
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
              Service = "ecs-tasks.amazonaws.com"
            }
          }]
        })
      }

      resource "aws_iam_role_policy_attachment" "ecs_task_execution_policy" {
        role       = aws_iam_role.ecs_task_execution_role.name
        policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
      }

Explanation:

  • ECS needs permissions
  • Pull Docker image
  • Send logs to CloudWatch

7. ecr.tf

      resource "aws_ecr_repository" "repo" {
        name = "springboot-repo"
      }

Explanation:

  • Docker image storage

8. ecs-cluster.tf

      resource "aws_ecs_cluster" "main" {
        name = "springboot-cluster"
      }

Explanation:

  • ECS cluster creation

9. cloudwatch.tf

      resource "aws_cloudwatch_log_group" "logs" {
        name = "/ecs/springboot-app"
      }

Explanation:

  • Stores application logs

10. task-definition.tf

      resource "aws_ecs_task_definition" "app" {
        family                   = "springboot-task"
        network_mode             = "awsvpc"
        requires_compatibilities = ["FARGATE"]
        cpu                      = 512
        memory                   = 1024
        execution_role_arn       = aws_iam_role.ecs_task_execution_role.arn

        container_definitions = jsonencode([
          {
            name      = "springboot-container"
            image     = "${aws_ecr_repository.repo.repository_url}:latest"
            essential = true

            portMappings = [
              {
                containerPort = 8080
                hostPort      = 8080
              }
            ]

            logConfiguration = {
              logDriver = "awslogs"
              options = {
                awslogs-group         = aws_cloudwatch_log_group.logs.name
                awslogs-region        = "ap-south-1"
                awslogs-stream-prefix = "ecs"
              }
            }
          }
        ])
      }

Explanation:

  • Defines Docker container
  • CPU + memory
  • CloudWatch logging

11. alb.tf

      resource "aws_lb" "alb" {
        name               = "springboot-alb"
        internal           = false
        load_balancer_type = "application"

        security_groups = [aws_security_group.alb_sg.id]

        subnets = [
          aws_subnet.subnet1.id,
          aws_subnet.subnet2.id
        ]
      }

      resource "aws_lb_target_group" "tg" {
        name        = "springboot-tg"
        port        = 8080
        protocol    = "HTTP"
        target_type = "ip"
        vpc_id      = aws_vpc.main.id

        health_check {
          path = "/actuator/health"
        }
      }

      resource "aws_lb_listener" "listener" {
        load_balancer_arn = aws_lb.alb.arn
        port              = 80
        protocol          = "HTTP"

        default_action {
          type             = "forward"
          target_group_arn = aws_lb_target_group.tg.arn
        }
      }

Explanation:

  • ALB distributes traffic
  • Health check validates app health

12. ecs-service.tf

      resource "aws_ecs_service" "service" {
        name            = "springboot-service"
        cluster         = aws_ecs_cluster.main.id
        task_definition = aws_ecs_task_definition.app.arn
        desired_count   = 2
        launch_type     = "FARGATE"

        network_configuration {
          subnets = [
            aws_subnet.subnet1.id,
            aws_subnet.subnet2.id
          ]

          security_groups = [
            aws_security_group.ecs_sg.id
          ]

          assign_public_ip = true
        }

        load_balancer {
          target_group_arn = aws_lb_target_group.tg.arn
          container_name   = "springboot-container"
          container_port   = 8080
        }

        depends_on = [
          aws_lb_listener.listener
        ]
      }

Explanation:

  • Runs 2 containers
  • Connected with ALB
  • Fargate serverless deployment

13. autoscaling.tf

      resource "aws_appautoscaling_target" "ecs_target" {
        max_capacity       = 5
        min_capacity       = 2
        resource_id        = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.service.name}"
        scalable_dimension = "ecs:service:DesiredCount"
        service_namespace  = "ecs"
      }

      resource "aws_appautoscaling_policy" "cpu_policy" {
        name               = "cpu-autoscaling"
        policy_type        = "TargetTrackingScaling"
        resource_id        = aws_appautoscaling_target.ecs_target.resource_id
        scalable_dimension = aws_appautoscaling_target.ecs_target.scalable_dimension
        service_namespace  = aws_appautoscaling_target.ecs_target.service_namespace

        target_tracking_scaling_policy_configuration {
          target_value = 50

          predefined_metric_specification {
            predefined_metric_type = "ECSServiceAverageCPUUtilization"
          }
        }
      }

Explanation:

  • Auto scale when CPU > 50%
  • Minimum 2 tasks
  • Maximum 5 tasks

14. outputs.tf

      output "alb_url" {
        value = aws_lb.alb.dns_name
      }

Explanation:

  • Shows ALB URL after deployment

Terraform Commands

Initialize:

      terraform init

Check:

     terraform plan

Deploy:

     terraform apply

Destroy:

    terraform destroy

=================================================================================

In there are two type of lunch type

  1. EC2
  2. Forgot

To deploy a Spring Boot application on AWS Elastic Container Service (ECS), you'll typically follow these general steps:

  1. Containerize your Spring Boot application: You need to create a Docker image of your Spring Boot application. This involves writing a Dockerfile that defines the environment and dependencies required to run your application.

  2. Push Docker image to a container registry: You need to push the Docker image to a container registry like Amazon Elastic Container Registry (ECR) so that ECS can access it during deployment.

  3. Set up ECS Cluster: Create an ECS cluster where your containers will run. This involves defining task definitions, which specify how your containers should be run.

  4. Create ECS Service: Define a service within ECS that manages your tasks. This includes specifying the number of tasks you want to run, the load balancer configuration (if applicable), and other settings.

  5. Configure Load Balancer (optional): If your application requires load balancing, set up an Elastic Load Balancer (ELB) or Application Load Balancer (ALB) to distribute traffic to your ECS service.

Here's a basic example:

Dockerize your Spring Boot application:

Assuming you have a Spring Boot application with a Dockerfile like this:

Dockerfile

  FROM openjdk:11-jre-slim
  COPY target/my-spring-app.jar /app/my-spring-app.jar
  CMD ["java", "-jar", "/app/my-spring-app.jar"]

Build the Docker image:

 docker build -t my-spring-app .
 Push Docker image to ECR:
 First, ensure you have the AWS CLI configured and Docker installed.

Tag the Docker image:

  docker tag my-spring-app:latest <your-account-id>.dkr.ecr.<region>.amazonaws.com/my-spring-app:latest

Push the Docker image to ECR:

 aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.<region>.amazonaws.com
 docker push <your-account-id>.dkr.ecr.<region>.amazonaws.com/my-spring-app:latest

Set up ECS Cluster:

You can create an ECS cluster via the AWS Management Console or AWS CLI. You'll also need to create a task definition that specifies how your container should be run.

Create ECS Service:

Define a service within ECS to manage your tasks. Specify the task definition, desired number of tasks, and any load balancer configuration.

Configure Load Balancer (optional):

Set up an Elastic Load Balancer (ELB) or Application Load Balancer (ALB) to distribute traffic to your ECS service if required.

⚠️ **GitHub.com Fallback** ⚠️