Deploying a Flask App to AWS Beanstalk

In this article, we will go through deploying a flask application using AWS Beanstalk. Also, in this example, we will use a REST API, but the process is identical if you take a vanilla flask web application.

Deploying a Flask Application to AWS Elastic Beanstalk

What exactly is a Flask?

Flask is a Python-based web framework. It provides you with the necessary tools, frameworks, and technologies to create a web application. This web application can be as simple as a set of web pages, a blog, or a wiki, or as complex as a web-based calendar or a commercial website.

AWS Beanstalk

First, we’ll take a quick tour of AWS Beanstalk, and that’s handy if you have not used Beanstalk in the past; otherwise, you can skip to the subsequent sections ahead, where we will cover how we can create an application on AWS Beanstalk and in doing so we’ll take a look at the web-based console of AWS. Again, we won’t be doing any scripting using the CLI, so it’s just GUI web-based. Finally, once we have created an AWS Beanstalk application, we will look at how you can upload your custom Flask application to a devious Beanstalk. Again, we won’t be using the elastic beanstalks command-line interface – we will use the web-based GUI.

We’ll also package the Flask application and upload using the web-based GUI. Again, it gives us an idea of what the CLI possibly will be doing under the hood. In addition, we’ll learn a bit in terms of how AWS Beanstalk deploys applications and packages applications in that way.

What exactly is an AWS Beanstalk?

We would say AWS Beanstalk is part of Amazon’s set of computing services, and the fundamental concept behind AWS Beanstalk is simplifying the entire process and pipeline from the creation, deploying, managing, and scaling of our application.

AWS Beanstalk
AWS Beanstalk

The general idea is that it lets us focus more on our application. We don’t have to worry much about managing and scaling infrastructure because AWS Beanstalk does it for us. Using this idea of a managed container and specifically, the container stack that we will be looking at is for Python. AWS Beanstalk provides many other very popular web-based stacks like PHP, Ruby, Node, etc.

AWS Beanstalk is intended for delivering web-based applications or applications that use a web interface like REST API- it’s still based on HTTP protocol. That makes it an ideal candidate for AWS Beanstalk.

There’s this ongoing debate whether AWS Beanstalk is a platform as a service solution or more
of infrastructure as a service. In that regard, we would debate that Beanstalk is very close to being a platform as a service-based solution because, under the hood, Beanstalk leverages other infrastructure as service capabilities like EC2, for example. At the infrastructure level, the EC2 allows us to build applications and deploy using Beanstalk.

Because of the rapidity with which developers can create, test, and deploy apps, organizations consider a PaaS (Platform as a Service) solution a reliable tool for resolving their challenges. In addition, a PaaS solution allows you to fail faster, allowing you to iterate on your code modifications and deployment techniques more quickly.

Individuals and businesses can employ sophisticated development software and business intelligence and analytics solutions that they couldn’t afford to buy outright using a pay-as-you-go model.

Advantages of a PaaS solution

By establishing a reverse proxy in front of your application servers, Beanstalk is responsible for scaling your web servers. It can easily handle requests in the thousands at a time. Then your load balancers will start rotating the user’s requests to other application servers based on the auto-scaling policy you specified in the configuration settings. The latter happened when creating your application (only, of course, if you have chosen your environment to be load-balanced). Some popular PaaS options include Google App Engine, Heroku cloud, AWS Lambda, and Microsoft Azure Platform as a Service.

Overall, it’s all about simplifying the whole deployment and allowing us to deliver applications in a much more agile way.

In addition, AWS Beanstalk provides us a lot of other capabilities for us to scale the application, provide load balancing mechanism to provision applications, health monitoring auto-scaling, and various other services.

We dare say AWS Beanstalk is a perfect candidate for building both web applications and REST API.

Let’s go ahead with step one and build the Beanstalk application. So, if you log in to your AWS web console, you’ll find that AWS Beanstalk is right there under the compute set of services. Click on that, and you will be brought to an interface like the one below, where we can now create our first Beanstalk application. First, we’ll commence by creating a new application.

Welcome to AWS Elastic Beanstalk

Welcome to AWS Elastic Beanstalk

Keep in mind that AWS is constantly changing the GUI, and even at a particular point in time, we guess through things like they’d be testing to find different versions, look and feel. But, overall, the flow should be very similar or very consistent to what we have right now.

Application Information

Let’s give this a name, demo-eb-1, and try to keep the name unique. Then, we’ll see why you want it unique in just a bit on the next screen or part of the set of wizards that you come across next.

Application information:demo-eb-1
Application information: demo-eb-1

New Environment

You have the option of selecting whether it’s a web server environment or worker environment. Note that we are just building an API or even a standard web application. Therefore, you’ll want to choose to create a web server, as follows.

create a web server environment
create a web server environment

You get to select the platform to see that all the major or the most popular platforms are covered. For instance, .NET, Java, Node.js, PHP, Python, Ruby, Tomcat, Go, Packer, etc. We are going to be using Python. Again, all the major popular ones are covered as well. In addition, you can choose the option to deliver your solution using docker. That’s pretty exhaustive in itself.

Go ahead and select Python, and behind-the-scene, it’ll choose the Python 3.6 version, 64bit Amazon Linux. At this point, select a single instance or a load balance with auto-scaling capability. For development and R&D., For learning purposes, we will choose load balance with auto-scaling. Remember that if you do choose with load balancing, your cost will increase. Or you’d better want to shut down or terminate the service once you finish playing with it.

Environment Type

Environment Type

Application Version

Later on, we’ll upload our applications, but for now, let’s use the sample application, and we can leave much of these policies as is – don’t worry about it at this point.

Application version

Application version

Environment Information

Click next, and based on the name that we selected initially, it’s created some defaults for us. That’s why we mentioned checking for availability to ensure that you have a unique name on the environment information.

Click on next, and again keep in mind that this is a friendly environment name that will pop up in the GUI and on other screens.

Environment Information

Environment Information

Additional Resources

Now in terms of additional resources, there’s a ubiquitous model for building AWS Beanstalk -have your web application on REST API having a back-end. It can be some form of a relational database. You may want to create an RDS DB instance within the current environment and Amazon-hosted database service along with your application at this point. You may also opt to create your environment within a virtual private network (VPC).

additional resources
additional resources

But we would suggest that you don’t do that; instead, you create the RDS separately. Under databases, you can go ahead and make your RDS service separately. Otherwise, if you don’t do that, it kind of ties it or ties your RDS lifecycle into your application, and that’s not necessarily what we would want in most circumstances. So, as a result, it’s good to keep it independent. So, we would suggest not to click on these options at this time, and instead, if you require an RDS, provision it separately.

Configuration Details

We’ll use the default of a t1 micro – this is just for demo purposes, and that’s more than sufficient. Select your already existing EC2 key pair because we will not cover how to create key pairs in this article, assuming that’s something you’re already familiar with, and you can leave the rest of the sections less the way it is. Everything looks good.

configuration details
configuration details

Environment Tags

Let’s click on next. Herein, it is a good idea to set some environment variables. These can be used within your application. We won’t be utilizing that in this demo, but typically, things like an RDS and a database engine such as PostgreSQL, you want to keep the connection settings like the database name, server name, etc. Then you can pass them on as environment variables. You can set that here. However, we don’t need that for this demo.

Environment Tags
Environment Tags

Permissions

For things like permissions, let’s leave it as its default.

Permissions

Permissions

Review

Finally, take a look at the summary page – everything looks good.

Review
Review

Let’s go ahead and launch. The latter process will take a couple of minutes for it to launch, so it’ll be interesting also if you wanted to keep the EC2 panel open. Behind the scene, as we mentioned earlier, the elastic Beanstalk is trying to provision EC2 nodes.

Initially, there are no running EC2 instances as shown in the EC2 dashboard as follows in the diagram below.

No running EC2 instances on EC2 Dashboard
No running EC2 instances on EC2 Dashboard

So, if we click on running instances, it should come up in maybe a couple of seconds or minutes. In our case, it took about 2-3 minutes for the following EC2 instance to show up on the dashboard.

A new EC2 instance named demoEb1-em is provisioned & running
A new EC2 instance named demoEb1-em is provisioned & running

Meanwhile, dive in and examine the resultant event log. These comprise things like health or status. Since the elastic Beanstalk, it’s new, you can be sure enough to see as elastic Beanstalk is provisioning the services. In addition, it will also provide the underlying EC2 instances.

Event log
Event log

We’ve not selected a load balancer to have a highly available environment. There are lots of other settings that we could have set so that it’s more balanced. For instance, we could have provisioned multiple EC2 instances, but a single EC2 instance will get the job done for this purpose.

After it’s complete setting it up, you will note the other reason for having a unique name in the wizard- so it’s easy to detect. A key identifier for a complete process is the icon and the health status on the applications page. Check the image below as a confirmation.

publishing complete
publishing complete

The application has now been deployed. If you remember, we selected a sample application during the previous sections on the wizard. It is just a sample application that AWS provides, but we’ll look at deploying a custom Python Flask application. You’ll notice again that this is based on the stack that we selected that it’s used an Amazon Linux am running python 3.6.

There are a few exciting screens here, including the dashboard, configuration, logs, health, monitoring, alarms, managed updates, events, and tags provided by AWS. But we can look at them after deploying our intended Flask application. If you want to view the sample application, we have deployed it successfully. Click on the hyperlink on the right of the URL that will bring you to the following window that shows the sample application deployed on AWS elastic beanstalk.

sample application deployed on elastic Beanstalk
sample application deployed on elastic Beanstalk

Looking back at our plan, the first step was to create the AWS Beanstalk application, and we have just done that.

Creating Python Flask Application

Next, let’s go ahead and deploy our flask application to AWS Beanstalk. In this demo, we will create a simple hello application in Flask. It’s a rest application that displays the message “hello world” when you point it to the root URI.

Below is the code for the restful hello world application.

# application.py

from flask import Flask, request
from flask_restful import Resource, Api

application = app = Flask(__name__)
api =Api(app)

class HelloWorld(Resource):
	def get(self):
		return {'about':'Hello World!'}
		
api.add_resource(HelloWorld, '/')

if __name__=='__main__':
	app.run(debug=True)

That’s a straightforward application – the critical thing you’ll want to keep in mind specifically when working with AWS Beanstalk is how AWS Beanstalk is wired up with WSGI. The container expects a variable by the name application. So, in most stand-up Flask applications, they call it an app if you’re familiar with the standard way, but AWS Beanstalk expects the variable name, application, to be applied.

So instead of re-writing your entire code or removing any decorations of the sort app.something you have made, add the extra application as in the code above. It is less efficient, though, because you have to create another variable. Still, overall, it is not so bad given that you didn’t have to change anything in your already existing Flask application before uploading it to AWS. Not to raise the alarm, but in line with the previous information, name your application as application.py.

There are few things that we need to upload and deploy our application to AWS Beanstalk. We will do the first thing if you go to the terminal and navigate to your project folder; what we’ve done is create an environment called flask-demo. We highly recommend you use virtualenv because, interestingly, AWS Beanstalk under the hood uses virtualenv. So, keep it consistent.

Since we’ve already got an environment here and, in that environment, you want to install the dependency, so in our case, the two dependencies are flask and flask_restful. Therefore, all you need to do is do a pip install for Flask and then pip install Flask-RESTful as follows.

$ pip install Flask
$ pip install Flask-RESTful

Go ahead and install whatever libraries you need. The next thing that we will need to do is to package the file. This calls for us to create a requirements.txt file. The way you can do that is to do a pip freeze, as demonstrated below.

$ pip freeze
pip freeze
pip freeze

Because we’re already in an environment, it gives us all the libraries in this environment when we run pip freeze. We need Flask, and Flask-RESTful and the rest are just additional dependencies. Once you install these, there are other dependencies – we can either opt to send the two (Flask and Flask-RESTful ) or send the whole list of dependencies, and it should be fine. So, the simplest way is to do a pip freeze and send that to requirements.txt, as shown below.

$ pip freeze > requirements.txt

That’s the first resource that we needed. The next thing that we need is for us to upload and deploy the file. Therefore, we need to package our code and the requirements into a zip file. Since we only have one Python file and a requirements.txt file, we will go ahead and type it manually as follows. Let’s call it demo.zip.

$ zip demo.zip requirements.txt application.py
demo.zip
demo.zip

You’ll have a reasonably complex folder hierarchy in the real world, and you can exclude or include file types in a zip. Now that we have a zip file, we’ll upload and finally deploy our application.

Let’s go ahead and deploy it – behind the scene, what happens is that you have the AWS Beanstalk application created. Currently, it’s making this application or a managed container specifically for your application, and subsequently, it’s just deploying it. So behind the scene, what it does is, since we have uploaded the requirements.txt file, it’s running a pip install – r requirements.txt. Then it will move on to start provisioning our application.

$ pip install – r requirements.txt

In some cases, we don’t have any other dependencies, and these are all the dependencies that we can easily accomplish using simple pip commands. But in some cases, like you would have seen, like, say, for example, if you’re trying to install, say, a PostgreSQL database, just doing a pip install, and the PostgreSQL wouldn’t suffice. Instead, you will have to do something like an apt-get install or run a similar command. It only has to be supported in elastic Beanstalk, but we’re not covering that in this article.

After completing deployment, you will see that now the running version is a demo, and that’s the label that we provided, and the recent event shows everything is green. Therefore, we can proceed to test and see if it’s working. Sometimes you may need to refresh it or wait long enough. In our case, everything is alright, and we can see that this is a hello world application.

hello world application
Hello world application

Remember from our code above, all it’s doing is returning a JSON response having the words, “hello world.” For sure, that’s the expected behavior. So now, we have successfully deployed our application.

In summary, if you package your Python files and any other resource files and create a list of libraries that you need into a zip file and upload that to your AWS Beanstalk – that’s pretty much it.

Alternatively, you can go ahead and use the elastic beanstalk command-line interface. That’s the other option as well, and you will encounter it once you start building applications. However, you will most likely prefer using the CLI because it works very nicely with your development and git workflows. Furthermore, we highly recommend you research the elastic Beanstalk CLI further. Now, let’s go ahead and look at some of the other benefits and other screens in the AWS Beanstalk. Again, a lot of this has been configured through the wizard that we created initially.

According to our prior discussion, the benefits of the AWS Beanstalk is that it provides you all of these capabilities to scale your application – it provides auto-scaling and various other capabilities like we can scale it based on the on-demand scenario. So, you can help with all of those capabilities available in AWS Beanstalk if you want to scale up and scale down. You can set your schedule so that at different times of the day, like during working hours, you might want to add additional capacity than non-working hours or when you anticipate you can add more capacity in advance. That’s a handy feature in AWS Beanstalk.

There’s quite a lot of configurations therein, so we won’t be going through many details. But, still, typically, when you’re building a production application, we wouldn’t be going through the wizard as we did. And much of this will come into play now.

It was a straightforward application that doesn’t show many details around it, and since we have just provisioned it, it’s bound to be healthy. Still, it’s handy to know that AWS Beanstalk gives us a wealth of capabilities to monitor the entire lifecycle of the application and gives us an idea of the underlying resource utilization. However, because this is a straightforward application, it is not doing anything much.

For instance, we’re just calling it like a dozen times, or so it’s not going to be immediate or very, very close to real-time. But, still, we will find that it gives us a clear view that is not limiting in utilizing the underlying resource.

We also chose simple hardware that under the hood it’s still using a t1 micro, and we haven’t made any heavy calls at this point, so it’s not too stressed out the underlying hardware. Instead, it gives us visibility to the underlying health of the application, and that’s quite handy to have.

So, again if we find that the given resource is not able to handle the load, it gives us a quick insight into whether we need to provide additional capacity or not. In addition, there’s quite a lot more in AWS Beanstalk, but for this article, we will wrap it here and hope that your objective of knowing how to deploy a python flask application using elastic Beanstalk has been achieved.

I hope you liked the read, and it’s been helpful to help you get started using flask and AWS Beanstalk.

Similar Posts

One Comment

  1. Many thanks Humpfrey for the article,
    Very very usefull, I am facing the error below with my application deployment, as below.
    I was wondering if it’s something by any chance you can help with.

    Oct 17 00:43:08 ip-172-31-44-199 web: return self.load_wsgiapp()
    Oct 17 00:43:08 ip-172-31-44-199 web: File “/var/app/venv/staging-LQM1lest/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py”, line 48, in load_wsgiapp
    Oct 17 00:43:08 ip-172-31-44-199 web: return util.import_app(self.app_uri)
    Oct 17 00:43:08 ip-172-31-44-199 web: File “/var/app/venv/staging-LQM1lest/lib/python3.8/site-packages/gunicorn/util.py”, line 359, in import_app
    Oct 17 00:43:08 ip-172-31-44-199 web: mod = importlib.import_module(module)
    Oct 17 00:43:08 ip-172-31-44-199 web: File “/usr/lib64/python3.8/importlib/__init__.py”, line 127, in import_module
    Oct 17 00:43:08 ip-172-31-44-199 web: return _bootstrap._gcd_import(name[level:], package, level)
    Oct 17 00:43:08 ip-172-31-44-199 web: File “”, line 1014, in _gcd_import
    Oct 17 00:43:08 ip-172-31-44-199 web: File “”, line 991, in _find_and_load
    Oct 17 00:43:08 ip-172-31-44-199 web: File “”, line 973, in _find_and_load_unlocked
    Oct 17 00:43:08 ip-172-31-44-199 web: ModuleNotFoundError: No module named ‘application’
    Oct 17 00:43:08 ip-172-31-44-199 web: [2021-10-17 00:43:08 +0000] [3568] [INFO] Worker exiting (pid: 3568)
    Oct 17 00:43:08 ip-172-31-44-199 web: [2021-10-17 00:43:08 +0000] [3562] [INFO] Shutting down: Master
    Oct 17 00:43:08 ip-172-31-44-199 web: [2021-10-17 00:43:08 +0000] [3562] [INFO] Reason: Worker failed to boot.
    Oct 17 00:43:09 ip-172-31-44-199 web: [2021-10-17 00:43:09 +0000] [3576] [INFO] Starting gunicorn 20.1.0
    Oct 17 00:43:09 ip-172-31-44-199 web: [2021-10-17 00:43:09 +0000] [3576] [INFO] Listening at: http://127.0.0.1:8000 (3576)
    Oct 17 00:43:09 ip-172-31-44-199 web: [2021-10-17 00:43:09 +0000] [3576] [INFO] Using worker: gthread
    Oct 17 00:43:09 ip-172-31-44-199 web: [2021-10-17 00:43:09 +0000] [3582] [INFO] Booting worker with pid: 3582
    Oct 17 00:43:09 ip-172-31-44-199 web: [2021-10-17 00:43:09 +0000] [3582] [ERROR] Exception in worker process
    Oct 17 00:43:09 ip-172-31-44-199 web: Traceback (most recent call last):

Leave a Reply

Your email address will not be published. Required fields are marked *