Skip to main content

AWS Elastic Container Service (ECS) - Create a Service and ALB LoadBalancer with HTTPS Listener and TLS Certificate using the AWS CLI, Mermaid Flowchart

2327 words·
AWS AWS CLI Elastic Container Service (ECS) Application Load Balancer (ALB) Elastic Container Registry CloudWatch Docker Mermaid Flowchart
Table of Contents

Flowchart
#

Main Architecture
#

Note: The HTTP Listener is not required and and was added for testing purposes.


graph TD %% User and Security Group 1 User(Access Application) -.->|LoadBalancer-SG| ALB %% Network Section subgraph NetworkSection[Network Section] %% Application Load Balancer ALB[Application Load Balancer
ALB] -.-> Listener1 ALB -.-> Listener2 %% Listener Listener1[Listener HTTP] Listener2[Listener HTTPS] Listener1 -.-> Target1 Listener1 -.-> Target2 Listener2 -.-> Target1 Listener2 -.-> Target2 %% Target Group subgraph LB-TG[Target Group] Target1[Target] Target2[Target] end end %% Certificate Manager Listener2 -.-> |TLS Certificate| CertificateManager((Certificate Manager)) %% ECS Cluster subgraph ECS[ECS Cluster] %% Service subgraph Service[Service] Task1[Task] Task2[Task] end end Target1 -.->|Container-fromLoadBalancer-SG| Task1 Target2 -.->|Container-fromLoadBalancer-SG| Task2 %% Dashed Border classDef themeColor2 stroke-dasharray:5 5; class ECS,NetworkSection themeColor2



Task Architecture
#

graph TD %% Cloudwatch subgraph Cloudwatch[Cloudwatch] loggroup[Log Group] end %% IAM subgraph IAM[IAM] Policy[Policy] --->|AmazonECSTaskExecutionRolePolicy| Role[Role] end %% Elastic Container Registry subgraph ECR[Elastic Container Registry] Repository[Repository] end %% Task Definition subgraph task-definition[Task Definition] executionRole[executionRole] containerDefinition[containerDefinition] logConfiguration[logConfiguration] end executionRole -.-> |ecsTaskExecutionRole| Role task-definition -.->|Create tasks| Task[Task] containerDefinition -.->|image| Repository logConfiguration -.-> loggroup



Prerequisites
#

Find Default VPC
#

# Find default Subnet
aws ec2 describe-vpcs \
    --filters Name=isDefault,Values=true \
    --region us-east-1 \
    --query "Vpcs[0].VpcId" --output text

# Shell output:
vpc-01c63f56b39dfh950

List Default Subnets
#

List the default subnets:

# List default subnets
aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-01c63f56b39dfh950 --query "Subnets[].SubnetId" --output text --region us-east-1

# Shell output:
subnet-0863f1a46bc384e59        subnet-0a68b63a736166ec5        subnet-018ce0a68d466f6b8        subnet-031bce85422909dd0        subnet-005aa1a09c535126c        subnet-08029536779973d55

List AWS Certificate ARN
#

# List the ARN of the AWS Certificate
aws acm list-certificates \
    --region us-east-1 \
    --query "CertificateSummaryList[*].{CertificateArn:CertificateArn,DomainName:DomainName}" \
    --output table

# Shell output:
---------------------------------------------------------------------------------------------------------
|                                           ListCertificates                                            |
+---------------------------------------------------------------------------------------+---------------+
|                                    CertificateArn                                     |  DomainName   |
+---------------------------------------------------------------------------------------+---------------+
|  arn:aws:acm:us-east-1:012345678912:certificate/ef60b545-2a1a-4fcb-988d-dd68cd491354  |  *.jklug.work |
+---------------------------------------------------------------------------------------+---------------+

Create CloudWatch Log Group
#

Create a log group in AWS CloudWatch logs:

  • A log group in AWS CloudWatch is a logical grouping of log streams.

  • Each ECS task or container generates logs, which are stored in individual log streams within the specified log group.

# Create a Cloudwatch log group
aws logs create-log-group \
    --log-group-name /ecs/example-task \
    --region us-east-1 \
    --no-cli-pager

IAM Role & Permissions
#

ECS Task Execution Role
#

  • The ecsTaskExecutionRole is required by ECS to pull the container images from the ECR
# Create the role "ecsTaskExecutionRole"
aws iam create-role \
    --role-name ecsTaskExecutionRole \
    --assume-role-policy-document '{
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "ecs-tasks.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }'

Attach Policy
#

Attach the managed AmazonECSTaskExecutionRolePolicy policy to the role:

# Attach policy to role
aws iam attach-role-policy \
    --role-name ecsTaskExecutionRole \
    --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

Verify the Role
#

# List role details
aws iam get-role --role-name ecsTaskExecutionRole

# Shell output:
{
    "Role": {
        "Path": "/",
        "RoleName": "ecsTaskExecutionRole",
        "RoleId": "AROARCHUALIN46RDYSU3J",
        "Arn": "arn:aws:iam::012345678912:role/ecsTaskExecutionRole",
        "CreateDate": "2024-12-12T17:27:12+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "ecs-tasks.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2024-12-13T17:24:21+00:00",
            "Region": "us-east-1"
        }
    }
}



Security Groups
#

Overview
#

Create two security groups:

  • A “LoadBalancer-SG”, that allows inbound traffic from HTTP / port “80” and HTTPS / port “443”, source anywhere “0.0.0.0/0”

  • A “Container-fromLoadBalancer-SG”, that allows inbound traffic from “All TCP”, source “Custom” “LoadBalancer-SG”


LoadBalancer Security Group
#

Create Security Group
#

# Create the "LoadBalancer-SG" security group
aws ec2 create-security-group \
    --group-name LoadBalancer-SG \
    --description "SG for the LoadBalancer" \
    --vpc-id vpc-01c63f56b39dfh950 \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "GroupId": "sg-046ac7fb3d1768354",
    "SecurityGroupArn": "arn:aws:ec2:us-east-1:012345678912:security-group/sg-046ac7fb3d1768354"
}

Add Inbound Rule
#

# Allow inbound traffic on port "80" / all sources
aws ec2 authorize-security-group-ingress \
    --group-id sg-046ac7fb3d1768354 \
    --protocol tcp \
    --port 80 \
    --cidr 0.0.0.0/0 \
    --region us-east-1 \
    --no-cli-pager
# Allow inbound traffic on port "443" / all sources
aws ec2 authorize-security-group-ingress \
    --group-id sg-046ac7fb3d1768354 \
    --protocol tcp \
    --port 443 \
    --cidr 0.0.0.0/0 \
    --region us-east-1 \
    --no-cli-pager

Container Security Group
#

Create Security Group
#

# Create the "Container-fromLoadBalancer-SG" security group
aws ec2 create-security-group \
    --group-name Container-fromLoadBalancer-SG \
    --description "SG for the ECS containers" \
    --vpc-id vpc-01c63f56b39dfh950 \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "GroupId": "sg-061c859568885966c",
    "SecurityGroupArn": "arn:aws:ec2:us-east-1:012345678912:security-group/sg-061c859568885966c"
}

Add Inbound Rule
#

# Allow inbound traffic on port "80" / all sources
aws ec2 authorize-security-group-ingress \
    --group-id sg-061c859568885966c \
    --protocol tcp \
    --port 0-65535 \
    --source-group sg-046ac7fb3d1768354 \
    --region us-east-1 \
    --no-cli-pager



Application Load Balancer (ALB)
#

Target Group
#

Create a Target Group
#

# Create a Target Group
aws elbv2 create-target-group \
    --name ecs-target-group \
    --protocol HTTP \
    --port 80 \
    --vpc-id vpc-01c63f56b39dfh950 \
    --target-type ip \
    --health-check-protocol HTTP \
    --health-check-path / \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "TargetGroups": [
        {
            "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
            "TargetGroupName": "ecs-target-group",
            "Protocol": "HTTP",
            "Port": 80,
            "VpcId": "vpc-01c63f56b39dfh950",
            "HealthCheckProtocol": "HTTP",
            "HealthCheckPort": "traffic-port",
            "HealthCheckEnabled": true,
            "HealthCheckIntervalSeconds": 30,
            "HealthCheckTimeoutSeconds": 5,
            "HealthyThresholdCount": 5,
            "UnhealthyThresholdCount": 2,
            "HealthCheckPath": "/",
            "Matcher": {
                "HttpCode": "200"
            },
            "TargetType": "ip",
            "ProtocolVersion": "HTTP1",
            "IpAddressType": "ipv4"
        }
    ]
}
  • The target group will direct HTTP traffic from the ALB to ECS tasks.

  • --target-type ip Used for tasks with awsvpc network mode.


Verify Target Group
#

# List the target group
aws elbv2 describe-target-groups \
    --region us-east-1 \
    --query "TargetGroups[*].{Name:TargetGroupName,ARN:TargetGroupArn,Protocol:Protocol,Port:Port}" \
    --output table

# Shell output:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                    DescribeTargetGroups                                                                     |
+------------------------------------------------------------------------------------------------------------+---------------------------+-------+------------+
|                                                     ARN                                                    |           Name            | Port  | Protocol   |
+------------------------------------------------------------------------------------------------------------+---------------------------+-------+------------+
|  arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d         |  ecs-target-group         |  80   |  HTTP      |
+------------------------------------------------------------------------------------------------------------+---------------------------+-------+------------+

Create Application Load Balancer
#

# Create an Application Load Balancer 
aws elbv2 create-load-balancer \
    --name ecs-alb-load-balancer \
    --type application \
    --scheme internet-facing \
    --ip-address-type ipv4 \
    --security-groups sg-046ac7fb3d1768354 \
    --subnets subnet-0863f1a46bc384e59 subnet-0a68b63a736166ec5 subnet-018ce0a68d466f6b8 subnet-031bce85422909dd0 subnet-005aa1a09c535126c subnet-08029536779973d55 \
    --region us-east-1 \
    --no-cli-pager


# Shell output:
{
    "LoadBalancers": [
        {
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca",
            "DNSName": "ecs-alb-load-balancer-1890637896.us-east-1.elb.amazonaws.com",
            "CanonicalHostedZoneId": "Z35SXDOTRQ7X7K",
            "CreatedTime": "2024-12-13T17:20:07.370000+00:00",
            "LoadBalancerName": "ecs-alb-load-balancer",
            "Scheme": "internet-facing",
            "VpcId": "vpc-01c63f56b39dfh950",
            "State": {
                "Code": "provisioning"
            },
            "Type": "application",
            "AvailabilityZones": [
                {
                    "ZoneName": "us-east-1d",
                    "SubnetId": "subnet-0863f1a46bc384e59",
                    "LoadBalancerAddresses": []
                },
                {
                    "ZoneName": "us-east-1a",
                    "SubnetId": "subnet-0a68b63a736166ec5",
                    "LoadBalancerAddresses": []
                },
                {
                    "ZoneName": "us-east-1f",
                    "SubnetId": "subnet-018ce0a68d466f6b8",
                    "LoadBalancerAddresses": []
                },
                {
                    "ZoneName": "us-east-1c",
                    "SubnetId": "subnet-031bce85422909dd0",
                    "LoadBalancerAddresses": []
                },
                {
                    "ZoneName": "us-east-1e",
                    "SubnetId": "subnet-005aa1a09c535126c",
                    "LoadBalancerAddresses": []
                },
                {
                    "ZoneName": "us-east-1b",
                    "SubnetId": "subnet-08029536779973d55",
                    "LoadBalancerAddresses": []
                }
            ],
            "SecurityGroups": [
                "sg-046ac7fb3d1768354"
            ],
            "IpAddressType": "ipv4"
        }
    ]
}

Retrieve ALB DNS Name
#

# Retrieve the DNS name of the ALB
aws elbv2 describe-load-balancers \
    --names ecs-alb-load-balancer \
    --region us-east-1 \
    --query "LoadBalancers[0].DNSName" \
    --output text \
    --no-cli-pager

# Shell output:
ecs-alb-load-balancer-1890637896.us-east-1.elb.amazonaws.com

Create DNS Entry with Route53
#

Create a DNS entry for the ALB LoadBalancer DNS name:

# Create route53 DNS entery
aws route53 change-resource-record-sets \
    --hosted-zone-id Z05838621L1SISL2CGD4M \
    --change-batch '{
        "Changes": [
            {
                "Action": "CREATE",
                "ResourceRecordSet": {
                    "Name": "ecs-alb-app.jklug.work",
                    "Type": "CNAME",
                    "TTL": 300,
                    "ResourceRecords": [
                        {
                            "Value": "ecs-alb-load-balancer-1890637896.us-east-1.elb.amazonaws.com"
                        }
                    ]
                }
            }
        ]
    }'

# Shell output:
{
    "ChangeInfo": {
        "Id": "/change/C04526942GZVR9RXE96A9",
        "Status": "PENDING",
        "SubmittedAt": "2024-12-13T18:22:48.777000+00:00"
    }
}

Create a Listener and Associate with Target Group
#

Wait till the ALB load balancer state changes from “Provisioning” to “Active”, this can take several minutes!


HTTP Listener
#

# Add a listener and specify the target group
aws elbv2 create-listener \
    --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca \
    --protocol HTTP \
    --port 80 \
    --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "Listeners": [
        {
            "ListenerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/b15e4163634ab930",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca",
            "Port": 80,
            "Protocol": "HTTP",
            "DefaultActions": [
                {
                    "Type": "forward",
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                    "ForwardConfig": {
                        "TargetGroups": [
                            {
                                "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                                "Weight": 1
                            }
                        ],
                        "TargetGroupStickinessConfig": {
                            "Enabled": false
                        }
                    }
                }
            ]
        }
    ]
}

HTTPS Listener
#

Add the ARN of the AWS Certificate Manager certificate arn:aws:acm:us-east-1:012345678912:certificate/ef60b545-2a1a-4fcb-988d-dd68cd491354

# Add a listener and specify the target group
aws elbv2 create-listener \
    --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca \
    --protocol HTTPS \
    --port 443 \
    --certificates CertificateArn=arn:aws:acm:us-east-1:012345678912:certificate/ef60b545-2a1a-4fcb-988d-dd68cd491354 \
    --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "Listeners": [
        {
            "ListenerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/31c0178f1e61e5d4",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca",
            "Port": 443,
            "Protocol": "HTTPS",
            "Certificates": [
                {
                    "CertificateArn": "arn:aws:acm:us-east-1:012345678912:certificate/ef60b545-2a1a-4fcb-988d-dd68cd491354"
                }
            ],
            "SslPolicy": "ELBSecurityPolicy-2016-08",
            "DefaultActions": [
                {
                    "Type": "forward",
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                    "ForwardConfig": {
                        "TargetGroups": [
                            {
                                "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                                "Weight": 1
                            }
                        ],
                        "TargetGroupStickinessConfig": {
                            "Enabled": false
                        }
                    }
                }
            ]
        }
    ]
}



AWS Elastic Container Registry (ECR)
#

Create ECR Repository
#

# Create a repository
aws ecr create-repository --repository-name example-app-with-lb --region us-east-1

# Shell output:
{
    "repository": {
        "repositoryArn": "arn:aws:ecr:us-east-1:012345678912:repository/example-app-with-lb",
        "registryId": "012345678912",
        "repositoryName": "example-app-with-lb",
        "repositoryUri": "012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb",
        "createdAt": "2024-12-13T17:32:51.881000+00:00",
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        },
        "encryptionConfiguration": {
            "encryptionType": "AES256"
        }
    }
}

Docker Login
#

Login the new registry repository:

# Retrieve an authentication token and authenticate the Docker client
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb

Push Image to ECR
#

Example Application
#

  • Dockerfile
# Use the official NGINX base image
FROM nginx:alpine

# Set working directory
WORKDIR /usr/share/nginx/html

# Remove default NGINX static files
RUN rm -rf ./*

# Copy your custom index.html file to the NGINX root directory
COPY index.html ./

# Expose port 80 for the web server
EXPOSE 80

# Start NGINX
CMD ["nginx", "-g", "daemon off;"]
  • index.html
<!DOCTYPE html>
<html>

<head>
    <title>jklug.work</title>
</head>

<body>
    <h1>Some HTML</h1>
    <p>Example Application with ALB Load Balancer<br></p>

</body>

</html>

Build the Image
#

# Build the image for the application
docker build -t example-application .

Tag the Image
#

# Tag the local Docker image to associate it with the ECR repository
docker tag example-application:latest 012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb:latest
  • Docker images deed a fully qualified name to push

Verify the image:

# List Docker images
docker images

# Shell output:
REPOSITORY                                                         TAG       IMAGE ID       CREATED          SIZE
012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb   latest    3e655c50b38d   18 seconds ago   49.3MB
example-application                                                latest    3e655c50b38d   18 seconds ago   49.3MB

Push the Image to ECR
#

# Push the image to ECR
docker push 012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb:latest

Verify / List Image in ECR
#

# List container images in the ECR repository
aws ecr list-images --repository-name example-app-with-lb --region us-east-1

# Shell output:
{
    "imageIds": [
        {
            "imageDigest": "sha256:1042c0f0885230c0b0d2bda3a4f2dd8c857829cd2e838efc0e2277938b2879b1",
            "imageTag": "latest"
        }
    ]
}



ECS Cluster
#

Create an ECS Cluster
#

  • Create a AWS ECS cluster with the default “Networking only” template, designed to use “AWS Fargate (serverless)”
# Create a AWS ECS cluster
aws ecs create-cluster --cluster-name jkw-cluster \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "cluster": {
        "clusterArn": "arn:aws:ecs:us-east-1:012345678912:cluster/jkw-cluster",
        "clusterName": "jkw-cluster",
        "status": "ACTIVE",
        "registeredContainerInstancesCount": 0,
        "runningTasksCount": 0,
        "pendingTasksCount": 0,
        "activeServicesCount": 0,
        "statistics": [],
        "tags": [],
        "settings": [
            {
                "name": "containerInsights",
                "value": "disabled"
            }
        ],
        "capacityProviders": [],
        "defaultCapacityProviderStrategy": []
    }
}

Task Definition
#

Create a Task Definition
#

  • The task definition focuses on container configuration, like image, CPU, memory and ports.

  • Task definitions are not directly tied to a cluster when they are created, they are later referenced when deploying a task or service to a specific cluster.

# Create a configuration file for the task definition
vi task-definition.json
{
  "family": "example-app-with-lb-task",
  "executionRoleArn": "arn:aws:iam::012345678912:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "example-app-with-lb",
      "image": "012345678912.dkr.ecr.us-east-1.amazonaws.com/example-app-with-lb:latest",
      "memory": 512,
      "cpu": 256,
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80,
          "protocol": "tcp"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/example-task",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "example"
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512"
}
# Register the task definition
aws ecs register-task-definition --cli-input-json file://task-definition.json --region us-east-1 --no-cli-pager

Verify / List Task Definition
#

# List ECS task definitions
aws ecs list-task-definitions --region us-east-1

# Shell output:
{
    "taskDefinitionArns": [
        "arn:aws:ecs:us-east-1:012345678912:task-definition/example-app-with-lb-task:1"
    ]
}

Create ECS Service
#

Add the previously created HTTP listener targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d in the --load-balancers section:

# Create a service with two task instances
aws ecs create-service \
    --cluster jkw-cluster \
    --service-name example-app-with-lb-service \
    --task-definition example-app-with-lb-task:1 \
    --desired-count 2 \
    --launch-type FARGATE \
    --network-configuration "awsvpcConfiguration={subnets=[subnet-0863f1a46bc384e59,subnet-0a68b63a736166ec5,subnet-018ce0a68d466f6b8,subnet-031bce85422909dd0,subnet-005aa1a09c535126c,subnet-08029536779973d55],securityGroups=[sg-061c859568885966c],assignPublicIp=ENABLED}" \
    --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d,containerName=example-app-with-lb,containerPort=80" \
    --region us-east-1 \
    --no-cli-pager



Verify the LoadBalancer
#

HTTP Version
#

Verify the application correctly connected to the ALB LoadBalancer:

# Curl the ALB LoadBalancer: Via HTTP listener
curl ecs-alb-load-balancer-1890637896.us-east-1.elb.amazonaws.com

# Shell output:
<!DOCTYPE html>
<html>

<head>
    <title>jklug.work</title>
</head>

<body>
    <h1>Some HTML</h1>
    <p>Example Application with ALB Load Balancer<br></p>

</body>

</html>

HTTPS Version
#

# Curl the ALB LoadBalancer: Via HTTPS listener
curl https://ecs-alb-app.jklug.work

# Shell output:
<!DOCTYPE html>
<html>

<head>
    <title>jklug.work</title>
</head>

<body>
    <h1>Some HTML</h1>
    <p>Example Application with ALB Load Balancer<br></p>

</body>

</html>



Cleanup
#

Delete the Service
#

# Delete the Service
aws ecs delete-service \
    --cluster jkw-cluster \
    --service example-app-with-lb-service \
    --force \
    --region us-east-1 \
    --no-cli-pager

Delete the Listeners
#

List Listeners
#

# List the Listeners
aws elbv2 describe-listeners \
    --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca \
    --region us-east-1 \
    --no-cli-pager

# Shell output:
{
    "Listeners": [
        {
            "ListenerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/31c0178f1e61e5d4",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca",
            "Port": 443,
            "Protocol": "HTTPS",
            "Certificates": [
                {
                    "CertificateArn": "arn:aws:acm:us-east-1:012345678912:certificate/ef60b545-2a1a-4fcb-988d-dd68cd491354"
                }
            ],
            "SslPolicy": "ELBSecurityPolicy-2016-08",
            "DefaultActions": [
                {
                    "Type": "forward",
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                    "ForwardConfig": {
                        "TargetGroups": [
                            {
                                "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                                "Weight": 1
                            }
                        ],
                        "TargetGroupStickinessConfig": {
                            "Enabled": false
                        }
                    }
                }
            ],
            "MutualAuthentication": {
                "Mode": "off"
            }
        },
        {
            "ListenerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/b15e4163634ab930",
            "LoadBalancerArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca",
            "Port": 80,
            "Protocol": "HTTP",
            "DefaultActions": [
                {
                    "Type": "forward",
                    "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                    "ForwardConfig": {
                        "TargetGroups": [
                            {
                                "TargetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-target-group/bc05444648763e1d",
                                "Weight": 1
                            }
                        ],
                        "TargetGroupStickinessConfig": {
                            "Enabled": false
                        }
                    }
                }
            ]
        }
    ]
}

Delete Listeners
#

# Delete HTTP Listener
aws elbv2 delete-listener \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/b15e4163634ab93 \
    --region us-east-1 \
    --no-cli-pager

# Delete HTTPS Listener
aws elbv2 delete-listener \
    --listener-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:listener/app/ecs-alb-load-balancer/d9b7d7a61588dcca/31c0178f1e61e5d4 \
    --region us-east-1 \
    --no-cli-pager

Delete the LoadBalancer
#

# Delete the ALB LoadBalancer
aws elbv2 delete-load-balancer \
    --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:loadbalancer/app/ecs-alb-load-balancer/d9b7d7a61588dcca \
    --region us-east-1 \
    --no-cli-pager

Delete the Target Group
#

# Delete the Target Group
aws elbv2 delete-target-group \
    --target-group-arn arn:aws:elasticloadbalancing:us-east-1:012345678912:targetgroup/ecs-exampl-nginx-service/2366ce2adff85384 \
    --region us-east-1 \
    --no-cli-pager

Delete ECR Repository
#

# Delete the ECR repository
aws ecr delete-repository --repository-name example-app-with-lb --region us-east-1 --force

Delete ECS Cluster
#

# Delete the ECS Cluster
aws ecs delete-cluster \
    --cluster jkw-cluster \
    --region us-east-1

Delete the CloudWatch Log Group
#

# Delete the log group
aws logs delete-log-group \
    --log-group-name /ecs/example-task \
    --region us-east-1

Delete Task Definition
#

List Task Definitions
#

# List ECS task definitions
aws ecs list-task-definitions --region us-east-1

# Shell output:
{
    "taskDefinitionArns": [
        "arn:aws:ecs:us-east-1:012345678912:task-definition/example-app-with-lb-task:1"
    ]
}

Deregister Task Definition
#

# Deregister the task definition
aws ecs deregister-task-definition \
    --task-definition arn:aws:ecs:us-east-1:012345678912:task-definition/example-app-with-lb-task:1 \
    --region us-east-1 \
    --no-cli-pager

Delete Route53 DNS Entry
#

# Delete Route53 DNS entry
aws route53 change-resource-record-sets \
    --hosted-zone-id Z05838621L1SISL2CGD4M \
    --change-batch '{
        "Changes": [
            {
                "Action": "DELETE",
                "ResourceRecordSet": {
                    "Name": "ecs-alb-app.jklug.work",
                    "Type": "CNAME",
                    "TTL": 300,
                    "ResourceRecords": [
                        {
                            "Value": "ecs-alb-load-balancer-1890637896.us-east-1.elb.amazonaws.com"
                        }
                    ]
                }
            }
        ]
    }' \
    --no-cli-pager



Links #

# Tutorial
https://repost.aws/knowledge-center/create-alb-auto-register

# Amazon ECR Public Gallery
https://gallery.ecr.aws/