How to Deploy a Python Microservice on Fargate (Part 2)

Michael Card
6 min readMay 1, 2020

--

Photo by Manuel Geissinger from Pexels

In this two-part article, I will walk through the steps needed to deploy a Python microservice application on Amazon Web Services’ (AWS) Fargate service. For the purposes of this article, I will assume that you have already done all of the following:

  1. Have Python installed along with a Python IDE and the Bottle framework ( https://bottlepy.org/docs/dev/ ) and that you have successfully built and run the Bottle “hello world” program
  2. Downloaded and installed Docker ( see https://www.docker.com/products/docker-desktop )
  3. Created your own AWS account ( see https://portal.aws.amazon.com/billing/signup )
  4. Downloaded, installed and set up your profile for the AWS Command Line Interface ( aws-cli, see https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html )
  5. Downloaded and installed the AWS Elastic Container Service Command Line Interface (ecs-cli, see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_CLI_installation.html )

In the first part of this article, I walked through all the steps needed to get your Python microservice running in a Docker container on your computer and then to get that container image up into the AWS Elastic Container Repository (ECR) service. This second part of the article will walk through the steps to get your Python microservice up and running in AWS Fargate.

Step 1: First you will have to set up an AWS IAM role so that you can deploy a cluster in Fargate. To do this, create a file named task-execution-assume-role.json in the text editor of your choice and enter these contents:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Step 2: After you have created this file run this command using aws-cli:

aws iam --region us-west-2 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json

Note here that I used region us-west-2 as this is common for the AWS free tier, but you can use whatever region you want (just be consistent with whatever you chose for the steps in Part 1).

Step 3: Next, run this aws-cli command:

aws iam --region us-west-2 attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

You only have to perform these steps once for any AWS region you plan to deploy in.

Step 4: Next, you have to configure ecs-cli for the cluster you want to manage. You will need to perform steps 4 and 5 every time you want to create a cluster with a new name. First, run this command:

ecs-cli configure --cluster bottle-tutorial --default-launch-type FARGATE --config-name bottle-tutorial --region us-west-2

This sets up the ecs-cli tool so that the commands we issue next will be in the context of working with a cluster named bottle-tutorial running in us-west-2. You can choose any name you want for your cluster and any region you want (again, just be consistent with what you did for Part 1).

Step 5: Next, you have to set up a profile to allow access to the new cluster and its resources by providing your AWS access keys. Do this by running this command:

ecs-cli configure profile --access-key AWS_ACCESS_KEY_ID --secret-key AWS_SECRET_ACCESS_KEY --profile-name bottle-tutorial-profile

Step 6: After you have done these steps, you are ready to create a cluster for your microservice. To do this, run this command:

ecs-cli up --cluster-config bottle-tutorial --ecs-profile bottle-tutorial-profile

This command will create a cluster for you and return a result like this:

Cluster Creation Output

Take note of the subnet IDs for the two subnets that are created as well as the Virtual Private Cloud (VPC) ID as these will be used later.

Step 7: Next, retrieve the default security group ID from the VPC that was created in the previous command:

aws ec2 describe-security-groups --filters Name=vpc-id,Values=vpc-05c13e11fe1e0a2b2 --region us-west-2

Now this command will return a JSON document that looks like this:

{
"SecurityGroups": [
{
"Description": "default VPC security group",
"GroupName": "default",
"IpPermissions": [
{
"IpProtocol": "-1",
"IpRanges": [],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": [
{
"GroupId": "sg-0cea23d743e029910",
"UserId": “account_id_#”
}
]
}
],
"OwnerId": "account_id_#",
"GroupId": "sg-0cea23d743e029910",
"IpPermissionsEgress": [
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
],
"VpcId": "vpc-05c13e11fe1e0a2b2"
}
]
}

Step 8: Note here that the security group ID is contained in the “GroupId” field. You need the security group ID so that you can add a rule to it to open up the desired port (often port 80), though in this case we will open port 8080 as that is what the Bottle “hello world” application uses:

aws ec2 authorize-security-group-ingress --group-id sg-0cea23d743e029910 --protocol tcp --port 8080 --cidr 0.0.0.0/0 --region us-west-2

Obviously, when you run this on your computer you will use whatever security group ID is returned in the “GroupId” field.

We’re getting close!

Step 9: Next, create a Docker compose file for your application named docker-compose.yml using the text editor of your choice that has contents like this:

version: '3'
services:
web:
image: account_id_#.dkr.ecr.us-west-2.amazonaws.com/bottle-tutorial:lateste
ports:
- "8080:8080"
logging:
driver: awslogs
options:
awslogs-group: tutorial
awslogs-region: us-west-2
awslogs-stream-prefix: web

Now the key thing to note here is that for the “image:” field the value you put in there is the URI for your container that was shown in the Elastic Container Registry (ECR) in Part 1 of this article. This will cause the Elastic Container Service (ECS) to use your container that has the Bottle tutorial in it when it starts the microservice in the Fargate cluster.

Step 10: The other file you need to create for the Fargate deployment of the microservice is a file named ecs-params.yml. Use the text editor of your choice to create this file with the following content:

version: 1
task_definition:
task_execution_role: ecsTaskExecutionRole
ecs_network_mode: awsvpc
task_size:
mem_limit: 0.5GB
cpu_limit: 256
run_params:
network_configuration:
awsvpc_configuration:
subnets:
- "subnet-096a42170173ef018"
- "subnet-003b9ab8e79ece1b9"
security_groups:
- "sg-0cea23d743e029910"
assign_public_ip: ENABLED

Notice here that the subnet IDs are those returned by step 6 and the “security groups:” section includes the security group returned in step 7.

Step 11: Finally! Deploy your Dockerized microservice to Fargate with this command:

ecs-cli compose --project-name bottle-tutorial service up --create-log-groups --cluster-config bottle-tutorial --ecs-profile bottle-tutorial-profile

You should see output something like this:

Deploy ECS Service Output

Note that I have been running this multiple times to test it for this article so I had already created the log group, that is why there is a warning message in the above output. Nothing harmful, it’s just notifying that the log group with the specified name already exists.

Step 12: Examine container(s) running in your Fargate cluster with this command:

ecs-cli compose --project-name bottle-tutorial service ps --cluster-config bottle-tutorial --ecs-profile bottle-tutorial-profile

The output from this command will look something like this:

ps For ECS Running Containers Output

Step 13: Notice that the ps command shows you the IP address for the service. To verify that it is working, use the IP and port to access the service from your browser. Try entering

http://IP_ADDRESS:8080/hello/Fargate-Developer

in your browser’s address bar. You should get a result like this:

Output From Python Bottle Tutorial Running on Fargate

Step 14: To take down your microservice and release all the AWS resources it is using, first stop the container(s) running the service with this command:

ecs-cli compose --project-name bottle-tutorial service down --cluster-config bottle-tutorial --ecs-profile bottle-tutorial-profile

Step 15: Finally delete the cluster itself with this command:

ecs-cli down --force --cluster-config bottle-tutorial --ecs-profile bottle-tutorial-profile

And that’s it! Please feel free to let me know what you think of this article, and what kinds of other fun things you have found to try with deploying a service to Fargate!

--

--

Michael Card

Software engineer with a long career in the defense industry. Began commercial development soon after relocating to Austin TX in 2014.