AWS ECS - Let's play with it
Tags: aws, awsecs, ecs
Published: 2023-06-14 17:57:00

Lets start talking about AWS ECS service, what it is, what it does and so on.

For this article, lets assume that you already have a basic knowledge about containers and how they work (if not, please take a look at [](https://aws.amazon.com/docker)).

So, ECS states for Elastic Container Service and it is a container orchestration service where you can launch your container applications in an easily manner. It makes activities like deploy, manage and scale the applications much more easier.
As it is a service, you really don't need to worry or concern about hardware infrastructure, which is totally managed by AWS (as said, it is a fully managed service). In other words, if you want to run your containerized application on AWS without worry about infrastructure management, ECS is the right option.

To make things easier than before ECS is also fully integrated with AWS ECR (Elastic Container Registry), which is another AWS fully managed AWS service to push your container images. If you are used with Docker Hub, don't worry, it works as well !

We are ready to start, so first things first. Now it is time to visit the AWS ECR service :-)

When you work with ECS, you have 3 options for computing capacity. They are EC2 instances, Fargate and ECS Anywhere (using on premise resources). Lets explain a little bit about each one:

- EC2 instances: this type uses EC2 instances to have your services and tasks running, so you need to choose the instance family, instance size, number of instances and so on. In thi case, the instances are customized for ECS service and have the ecs-agent running on top of them.
- Fargate: this type of compute capacity is also know as serverless because you don't have EC2 instances to manage. You simply put your services and tasks to run and  nothing else.
- ECS Anywhere: this type of compute is the ability to register on premise servers to your ECS cluster (we will not touch on this inn this article !).

If you are in doubt on what type of compute capacity you use, you can take a look at this document: [](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/common_use_cases.html).

To make things simple, lets work with Fargate compute mode to run our containers. To start with that, first of all we need an ECS cluster, so lets create one. We have a lot of option to create our cluster, using AWS console, using CLI, using AWS SDK and other IaC tools like CloudFormation and Terraform for example. In our case, lets make it simple and use CLI.
Simply issue this command:

```
aws ecs create-cluster --cluster-name devto-ecs-cluster --capacity-providers FARGATE
```
You should have an output like that:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pc5t0pag8dl9kj1uk47.PNG)

To make sure the cluster is there, you can list it:

```
aws ecs list-clusters
```
You are able to see out cluster:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nie533qpoqvkqaxmmedk.PNG)

Now, our cluster is up and running, cool ! The next step is to create a task definition for our containers, but what is that ? Let me explain. 

Task Definition is a text file in JSON format that describes the containers and their parameters that will be part of the application. The parameters include CPU, memory, image name, IAM role, logging information and much more. You can visit this [](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_AWSCLI_Fargate.html#ECS_AWSCLI_Fargate_register_task_definition) to take a deeper look on task definitions.

That said, lets create out task definition. You can use any text editor, in my case I use vi to create a JSON file called devto-task-definition, like following:

```
{
    "containerDefinitions": [
        {
            "name": "devto-article-container",
            "image": "<your_account_id>.dkr.ecr.us-east-1.amazonaws.com/my-ecs-container-repo",
            "cpu": 0,
            "portMappings": [
                {
                    "name": "devto-article-container-80-tcp",
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp",
                    "appProtocol": "http"
                }
            ],
            "essential": true,
            "environment": [],
            "environmentFiles": [],
            "mountPoints": [],
            "volumesFrom": [],
            "ulimits": [],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-create-group": "true",
                    "awslogs-group": "/ecs/devto-task-definition",
                    "awslogs-region": "us-east-1",
                    "awslogs-stream-prefix": "ecs"
                }
            }
        }
    ],
    "family": "devto-task-definition",
    "taskRoleArn": "arn:aws:iam::<your_account_id>:role/EcsTaskRole",
    "executionRoleArn": "arn:aws:iam::<your_account_id>:role/ecsTaskExecutionRole",
    "networkMode": "awsvpc",
    "volumes": [],
    "placementConstraints": [],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "256",
    "memory": "512",
    "runtimePlatform": {
        "cpuArchitecture": "X86_64",
        "operatingSystemFamily": "LINUX"
    }
}
```
"Pay attention that I replaced my account id by the string <your_account_id>. In your case, it should be your own account id."

With the task definition file created, we need to register this task definition so ECS is able to reference when creating a service or task. To do that, just issue the following command:

```
aws ecs register-task-definition --cli-input-json file://devto-task-definition.json
```

To make sure the task definition has been successfully created, you can issue the command to confirm:

aws ecs list-task-definitions

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8b4d0q08pfpwy12zz4kc.PNG)

With the task definition registered, we are finally able to run our task in our ECS cluster (Uhuuuuulll !!!). To do that, lets create a service to run our task and test it from a browser on the internet. To do that, take note about the subnet-id you will deploy the service, the security group for that service (as this is an example, lets use a security group allowing access from internet on port 80) and lets assign a public IP to that, so we will be able to test it from anywhere. With all required information, lets simply issue the following command:

```
aws ecs create-service --cluster devto-ecs-cluster \
--service-name devto-article-service \
--task-definition devto-task-definition \
--desired-count 1 \
--launch-type "FARGATE" \
--network-configuration "awsvpcConfiguration={subnets=[subnet-014d9c5f9d0bb9b90],securityGroups=[sg-03eb793e06078aabe],assignPublicIp=ENABLED}"
```
To make sure the service has been created, lets list the services running in our ECS cluster with the following command:

```
aws ecs list-services --cluster devto-ecs-cluster
```
Yes, our service is right there:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xddbimttu7wjsaj3np6.PNG)

Now our container app is running in a service on top of the ECS cluster, that is great !!! So, time to test it. As we deployed in a public subnet to make it available to test in the internet, we need to find the public IP address that was assigned to out task in the service. To grab this information, lets run some commands ! 

First, lets list our task to get the arn. Issue the following command:

```
aws ecs list-tasks --cluster devto-ecs-cluster --service devto-article-service
```
It will output the task arn:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07m6d4iyfzy6rg5xi7il.PNG)

Now, lets describe this task using the arn, so we will be able to check which network interface it is using and with that information, check the public IP assigned to the task. Just issue the following command:

```
aws ecs describe-tasks \
--cluster devto-ecs-cluster \
--tasks arn:aws:ecs:us-east-1:<your_account_id>:task/devto-ecs-cluster/defc81a93bda4df6ad73957ef718876e
```
"Pay attention that I replaced my account id by the string <your_account_id>. In your case, it should be your own account id."

Look for the "networkInterfaceId" value as shown bellow:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n13i4zbtt0bzdcz0k2nd.PNG)

With the network interface id, we can easily discover the IP address with a describe command. Just issue the following command:

```
aws ec2 describe-network-interfaces \
--network-interface-id eni-0765281dfd52d2b06
```
The output will be as shown bellow:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j4e5b2mf6y2j1hy6o8qo.PNG)

What amaaaaazing news !!! Now we can test our application from a browser and make sure it is running as expected. So what are we waiting for ? Lets try it right now !!! Lets put the public IP in a browser and have our fingers crossed:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rwodmqkgdbvlw8mcy4b.PNG)

Uaaaaauuuu !!! After some commands, we are finally done with our mission to have a container application running on a ECS cluster as required. 

You did a great job. Thank you so much for follow me in this article and see you in the next.

sources:
https://aws.amazon.com/getting-started/hands-on/deploy-docker-containers/
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-container-image.html
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_AWSCLI_Fargate.html#ECS_AWSCLI_Fargate_register_task_definition