Dockerize an API based Flask app and deploy on Amazon ECS
Tags: docker, aws, devops, cloud
Published: 2022-04-17 19:46:52

Hi Folks!
This is the first blog of the series Dockerize Your Application.

In the age of microservices we want our application code and requirements to be packed in an image and use that in a suitable container orchestration tool for better scalability and availability.

## Pre-Requisites:
- An EC2 Server with git and docker installed
- Amazon ECR Repository 
- AWS CLI configured on your server with sufficient permissions (to push image to ecr) or you can attach a role to your server with sufficient permissions.
- Region: Mumbai(ap-south-1)

## About the API
It's a todo app with two API's one to get the list of to-do tasks and another to post your tasks.
GET-POST api path - /todo/api/v1.0/tasks

## Source: [Flask_API_App]
(https://github.com/RajitPaul11/AWS_workshop_2022_data/tree/collate/python_flask_code_in_aws_linux_restful_GET_POST)

## Dockerfile

```
FROM alpine:latest

RUN apk add py3-pip
RUN pip3 install flask

WORKDIR /home

COPY app.py .

EXPOSE 80

ENTRYPOINT ["/usr/bin/flask","run"]

CMD ["--host=0.0.0.0", "--port=80"]
```

#### Login to your EC2 Server and clone the repo

git clone -b collate https://github.com/RajitPaul11/AWS_workshop_2022_data.git

#### Change directory and build docker image
cd AWS_workshop_2022_data/python_flask_code_in_aws_linux_restful_GET_POST
docker build -t flask_api_app:v1 .

#### Tag your docker image
docker tag flask_api_app:v1 youraccountID.dkr.ecr.ap-south-1.amazonaws.com/flask_api_app:v1

#### Login to your ECR Repo
aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin youraccountID.dkr.ecr.ap-south-1.amazonaws.com

#### Push the docker image
docker push youraccountID.dkr.ecr.ap-south-1.amazonaws.com/flask_api_app:v1

## Deploy to ECS
Select Services and then select ECS
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0n253ojchn5r8o1rkax7.png)

#### Create an ECS Cluster
We shall be creating an ECS Cluster with EC2
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6esm057mii97vnrfk3d5.png)

#### Cluster Config
Choose a suitable name for your cluster, and select a provisioning model, in this case we shall go for Spot.
Choose diversified spot instance allocation strategy so the instances are spread across az's.
Select two instance types on a or basis.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/op9cquaf6rhkmwskqvij.png)

Specify the Storage spec and select an existing key pair, so that you can ssh later to the EC2 instance and do some modification or troubleshoot from the terminal.
Create a new VPC or you can select an existing VPC.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a2oab7a93mhfcku7i1wi.png)

Cluster created!
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mrhg8hu8q4bu0u1rc4wl.png)

## Create a Task Definition
Select the launch type as EC2
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8mv0rck1s5j13ox1vzm.png)
Provide a suitable task def name, and select the Task Role and network mode (we shall be looking into the different network modes in an upcoming blog, for now let's go ahead with bridge), select a task execution role.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxnb7xvlie7ix9o9hcuq.png)
Allocate sufficient task memory and cpu based on your application requirements.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oy0czikg1jtf4zoov74m.png)
#### Add a container
Provide a container name and the ecr repo uri along with the version, you can set hard limit for the container in case you have set the task cpu and memory req this is not required, if you want dynamic port mapping, keep the host port as 0, in this case we have set it to 80 same as the container port
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29oxkvhz3271nauybpmq.png)  
As per requirement you can explore advanced details and set container healthcheck, container timeouts, storage, logging and more.

## Create a Service
Select the launch type as EC2, select your task definition and it's version you can see the latest suffix to denote the latest version, select your cluster and provide a suitable service name, select a service type (in this case we shall go with replica), provide the number of tasks you want to run (keep in mind the instance type you chose and the resource allocated to each task while you designate the number of tasks)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23yjaoe3lhhkj18gjq9p.png)
Select the deployment strategy (we shall go into depth on this in an upcoming blog, in this case we choose Rolling Update), select a Task Placement strategy (AZ Balanced spread will help to spread tasks across instances in different AZ's for high availability)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vuujt19dg1dtf9xl5qej.png)

## Configure a Load Balancer
Select your load balancer type(in this case we choose application load balancer), Create a new service IAM role, and select your existing Load Balancer.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pp4k7jczmtr3j47dkly0.png)
In your target group you can register the existing ECS instance, and set the health check path as /todo/api/v1.0/tasks
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbx1d04dk6l7wo85twdw.png)
If you want to scale your tasks you can enable autoscaling, in this case we do not want to scale our tasks so we won't enable auto scaling.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/krye8tqr1m5yl40suwpy.png)
Select your listener, target group name for the Load Balancer and rest shall be populated
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69hcx5r8vdx6ipcp1puo.png) 
Service Created and Task Running!
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s539oeb2xivvcbvnv5yu.png) 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwvjxx2jix22xhhw109z.png) 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jdjquwal08ha1e0rimf.png)
 
   
Allow Port 80 in EC2 and ALB
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf7u0qi476kzpjqnw6lb.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wkv0uzt1yh0xqc5dmlbb.png)

## Test API using ALB URL 
#### GET Request
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjdp3gdr5x7q735s5awp.png)
#### PUT Request
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rjdw34sqmxon156gjt8q.png)


If you have any queries you can connect with me on [LinkedIn](https://www.linkedin.com/in/rajitpaul/)