Deploying a Python Flask Web Application on AWS Cloud ☁️

Deploying your web app onto cloud is easier than it sounds like. The AWS (Amazon Web Services) cloud platform offers a range of utilities to host your web app on their servers and forget the stress of maintaining one yourself. The cost and time involved in running a server is what stops many from web app development. In this tutorial you will learn how to host your containerised python flask web application on an AWS Elastic Compute Cloud (EC2) instance or a simple server running in one of Amazon’s data centres.

It is assumed that you already have a Dockerised web app in hand. If not, you can learn how to create one from my earlier tutorial or download a sample one from my git repository here.

To start this tutorial, you will need to sign up for a free tier account with AWS. You can do it here. Make sure you create an IAM role with Administrator access and sign in using that IAM role. It is not wise to work from your root AWS account. In fact, it is recommended that you create an IAM role for all of your specific uses, like for instance, doing this tutorial. But, for now, let’s just keep things simple and work from the admin IAM role.

After signing into the AWS console using your admin IAM role, navigate to the EC2 service page. You can do this by clicking on the “Services” tab at the top and typing in EC2. The page should look, as of now, like this:

From the EC2 console, click on the “Launch Instance” button. Choose the “AWS Linux 2 AMI” machine image and make sure it’s “free-tier” eligible. Click “Select” and then choose “t2.micro” as the type of your instance, which again should be “free-tier” eligible. Now, click on “Next: Configure Instance Details”. Here, you need to leave all of the configuration as it is, except the IAM role for your instance. Let’s create a new IAM role for our specific use. Click on “Create IAM role” next to the IAM field. This will open the IAM console in a new browser tab.

From the IAM console, click on the “Create role” button. For the “AWS Trusted Entity” keep the default “AWS Service” option and under “Choose a Use Case” select EC2. Click on “Next: Permissions”. Search for “EC2FullAccess” and “ssm-kms-policy”. The “ssm-kms-policy” is what allows you to log into the instance. If you don’t see the “ssm-kms-policy” policy, just create a new policy with the same name and using following JSON:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:GetEncryptionConfiguration",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::dcp-685169213993-eu-west-2-logs"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"cloudwatch:PutMetricData",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"kms:*",
"ssm:*",
"ec2messages:*",
"ssmmessages:*",
"logs:CreateLogGroup",
"logs:PutLogEvents",
"kms:ReEncrypt*",
"ec2:DescribeInstanceStatus"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload"
],
"Resource": "arn:aws:s3:::dcp-685169213993-eu-west-2-logs/session-manager/*"
}
]
}

Once you have selected both of those policies click on “Next: Tags”. Leave everything as it is and click on “Next: Review”. Give the IAM role a suitable name like “ec2-role” and click on “Create role”.

Now let’s go back to launching our EC2 instance. Click on the refresh button next to the IAM role drop-down and select the role you just created from the drop-down menu. Click on “Review and launch” and click on “Launch”. You will get a pop-up asking you to select a key pair. Choose to proceed without a key pair and tick the acknowledgement message. Click on “Lauch instances”. AWS should now begin creating your instance and booting it up. Wait for the green “running” status.

We’ll connect to the EC2 instance using a session manager. Select the instance and click on “Connect” and select the Session Manager option and click on the “Connect” button. This should open a CLI in a new tab. Switch to the “sudo” user by typing in:

$ sudo su

Now, we need to install a couple of prerequisites, namely — git and docker:

$ yum update -y
$ yum install -y git docker

The “-y” tag tells yum not to prompt for confirmations.

After the install is finished, we will create an “/apps” directory and clone our web app into it using git. Here I am using a simple flask app I created in an earlier tutorial. You can find the git repository here.

$ mkdir /apps
$ cd /apps
$ git clone https://github.com/artk-dev/simple-dockerised-flask-app.git
$ cd simple-dockerised-flask-app

Next, start up the docker daemon using this command:

$ systemctl start docker

Now let’s build our Docker image and start the Docker container from it. We will also map port 80 of the EC2 instance to port 90 of the container. This can be done within the docker run command using “-p”.

$ docker build -t app:latest .
$ docker run -d -p 80:90 -t app:latest

To see if the setup so far is working right, let’s curl the local port 80 of the instance. If your output gives you “Hello World” then everything’s set up properly.

$ curl localhost:80

Here, you don’t really have to specify port 80, since port 80 is the default port where TCP and HTTP requests are sent.

Great! Now we have everything set up inside our EC2 instance. But before we can access our web app using the instance’s public IP, there is one more step: We need to configure the right security group for the instance.

Security groups allow us to control traffic that goes in and out of one or more of our instances. You can add one or multiple security groups to an instance. You can assign inbound and outbound rules to the security group allowing specific type of traffic using specific protocols coming from specific sources and hitting specific ports of our instance. Or you can just allow all traffic from anywhere. The same applies to outbound traffic. It essentially “acts as a virtual firewall” as described by AWS.

Even though there is a security group attached to our instance by default, let’s create a new one for our use. On the EC2 console click on “Security Group” from the left-hand pane and then click on “Create security group”. Give the security group a suitable name and a description. Now, under “Inbound rules” click on “Add rule”. Create a rule of type “HTTP” and source type “Anywhere” and click on “Add rule”. Keep the default outbound rule of type “All traffic”. Now, click on “Create security group”. What we just did is create a security group that allows all HTTP traffic into the group through port 80. All outbound traffic from the group is also allowed. Now, we need to attach this security group to our EC2 instance.

Go back to the Instances page from the left-hand pane and right-click on our instance. Navigate to “Networking” and then click on “Change Security Groups”. Deselect the security group that is already attached to the instance and select the one we just created. Click on “Assign Security Groups”.

Awesome, users around the world will now be able to access our web app using the public IP address or the DNS name of our instance. Copy either of those on to a new browser tab and see what happens!

… Hope this helps you start your cloud journey with AWS!

Budding software engineer with experience in full-stack development and DevOps engineering. 📚 Love to code. ⌨️ Love to write.✒️