Create a Simple Flask App on EC2

Recently, I was faced with a situation where I had to quickly create a simple service in Python that I could invoke and run some real time tests based on the input data. I spend a few minutes searching about the quickest way to achieve this and came across Flask. It is very easy to develop a Flask app, or to convert an existing Python app to use Flask and make it in a service. It is not something we will use in production as is, but for development, it totally works awesome.

The steps below will show how in a few quick few steps we can create a Flask app and run it on an EC2 instance.

Step1: Create a Virtual Env on EC2

The very first step is to create an EC2 instance and a virtual environment for our app. The detailed steps for creating a virtual environment can be found in my other post titles Create Python Virtual Environment on AWS EC2.

Step2: Install Flask

I have my virtual environment ‘flask_env’ created as part of the previous step. Now lets install Flask in out environment using pip as shown below. Make sure to activate your environment. Once the installation completes successfully, we can check the version to make sure it was installed properly.

ubuntu@xxxx:~/venv$ source /home/ubuntu/venv/flask_env/bin/activate
(flask_env) ubuntu@xxxx:~/venv$ pip3 install --no-cache-dir flask
(flask_env) ubuntu@xxxx:~/venv$ flask --version
Python 3.6.9
Flask 1.1.2
Werkzeug 1.0.1

Step3: Create Flask App

We are not ready do create our first Flask app. Here I am creating just a Hello World app, but it very easy to extend this to add more routes and more functionality as needed. To create the app –

  1. Import flask.
  2. Create flask instance.
  3. Create a function that performs the required functionality, in this case it just means return ‘Hello World’.
  4. Run the flask app.

Below is how can achieve this.

(flask_env) ubuntu@xxxx:~/venv$ mkdir /home/ubuntu/flask_test
(flask_env) ubuntu@xxxx:~/venv$ cd /home/ubuntu/flask_test
(flask_env) ubuntu@xxxx:~/flask_test$ vi app.py

In the editor that opens up, copy the code shown below. The last line is what will start the flask app. I have provided ‘debug=True’ as I am still in development phase and would like to see the logs printed out. But this can be turned off once everything goes as expected. In addition to this, we can pass the ‘host’ and ‘port’ where we want the flask app to serve. Since I have left these options out, the app will serve at the default port of 5000 on localhost (=127.0.0.1).

from flask import Flask
  
# a flask instance
app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return 'Hello World!'

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

Step4: Run the App

Now that we have our code ready, let us run it and see if it works or we have any errors. Note that I am inside the directory I create for my app file. There are two ways we can run this app –

  1. Run a python app
(flask_env) ubuntu@xxxx:~/flask_test$ python app.py 
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!

2. Flask run

(flask_env) ubuntu@ip-172-31-85-173:~/flask_test$ flask run
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/

As seen above, in both cases, our app started running. We see a line in the output printed that shows where this app is serving and as mentioned before, since we did not specify any host or port, it is serving at the local host (127.0.0.1) and the default port 5000.

To run this app in the background, just add nohup in the beginning and an ampersand at the end.

(flask_env) ubuntu@xxxx:~/flask_test$ nohup python app.py & 
[1] 22018
(flask_env) ubuntu@xxxx:~/flask_test$ nohup: ignoring input and appending output to 'nohup.out'
(flask_env) ubuntu@xxxx:~/flask_test$
Running on http://127.0.0.1:5000/

Step5: Access the Service

Now that our app is running, we can finally hit the service and see our app in action. So how do we access it? It is being served at 127.0.0.1:5000. So should we be able to just type that in our browser and get the response back? On trying this, we will see that this will not work and we will get “This site can’t be reached”. The problem is, we do not have any web server running that will take out web request is pass it to our app that is running.

So how do we access this? We can create a tunnel to our EC2 host, giving us access on our localhost. We can do so by running the following in a new terminal –

ssh -i /path_to_pem_file/myPEM.pem -L 5001:localhost:5000 ubuntu@ec2-xxxx.compute-1.amazonaws.com

When we make a connection using this command, any traffic that comes from localhost:5001 will be forward to the port 5000 on our server, which for us is where the flask app is serving. So now, let us try to access localhost:5001 and see what happens. As soon as we hit that in our browse, we will see this –

Hello World!

Yay! we just ran and got served by our first Flask app.

This however, is just a development setup. We cannot create tunnels and function this way in production. In the next post, I will show how we can use WSGI and NGINX to run this same app.

Leave a Reply

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