Deploying multiple Python 3 Flask apps to AWS using Nginx

A complete working tutorial for deploying Flask App to AWS EC2 using Python3 and Nginx

Prithvi Shetty
4 min readMay 21, 2020

Steps:

  1. Create an Ubuntu EC2 instance and log in to it.
  2. Install the requires libraries and packages.
  3. Create a simple Flask application.
  4. Configure Nginx settings
  5. Configuring Gunicorn as a service
  6. Restart nginx, gunicorn service and GO
  7. Setting up multiple Flask apps

1.Create an Ubuntu EC2 instance and log in to it.

Connect to your EC2 instance using this command:

(Make sure you are in the same folder where the key-pair PEM file is stored)

ssh -i <keypairname.pem> ubuntu@<instance name/IP>

2. Install all the required libraries and packages

$ alias python=python3
$ alias pip=pip3
$ sudo apt-get update
$ sudo apt-get install nginx
$ sudo apt-get install gunicorn3
$ pip install flask #(or pip install -r requirements.txt if you have multiple libraries)

3. Deploy a simple Flask application and run it.

$ mkdir flask_aws
$ mkdir flask_aws/templates flask_aws/static
$ vim flask_aws/templates/index.html

Enter the following code in index.html :

<body>
<h2>
Testing flask application for AWS EC2
</h2>
</body>

Write and save the code by pressing :wq! Further, create the flask app

$ vim flask_aws/app.py

Enter the following contents in app.py and save it:

from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route("/") def home():
return render_template("index.html")

4. Configure Nginx settings

$ sudo vim /etc/nginx/sites-enabled/flask_aws

Enter the following in the config file and save it:

server {
listen 80;
server_name 0.0.0.0;

location / {
proxy_pass http://127.0.0.1:8000;
}

}

Restart Nginx:

$ sudo service nginx restart$ cd 
$ cd flask_aws
$ gunicorn3 app:app
Output after launching the app through Gunicorn

$ curl 127.0.0.1:8000

This should give the following output:

Output for the curl command

5. Configuring Gunicorn service

$ sudo vim cd /etc/systemd/system/flask_aws.service

Enter the following in the flask_aws.service file:

[Unit]Description=AWS Flask appAfter=network.target[Service]User=ubuntuGroup=www-dataWorkingDirectory=/home/ubuntu/flask_awsExecStart=/usr/bin/gunicorn3 —-workers 3 --bind unix:flask_aws.sock -m 007 app:app

The directory structure looks like this:

Directory structure (Ignore the Pycache folder)

That’s it! Do the following changes, restart the service and DONE!

$ sudo systemctl daemon-reload
$ sudo service flask_aws restart
$ sudo vim /etc/nginx/sites-enabled/flask_awsIn the config file, change the following:
1)Proxy pass to http://unix:/home/ubuntu/flask_aws/flask_aws.sock
2)
Server name to <Public IP of EC2 instance>
$ sudo service nginx restart

You should able to view the website on the EC2 instance’s public address

The final output in the browser

7. Setting up multiple Flask apps

The procedure remains entirely the same except for the fact that we have to do it twice and host the other application on the same EC2 public address but different ports.

Steps for the second Flask App:

$ mkdir flask_aws1
$ mkdir flask_aws1/templates flask_aws1/static
$ vim flask_aws1/templates/index.html
Enter the following in the html file<body>
<h2>
Testing multiple flask applications for AWS EC2
</h2>
</body>

Create a Python file:

$ vim flask_aws1/app.py

Add the following contents to the file:

from flask import Flask
from flask import render_template
app=Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")

Configure the nginx settings for the new Flask app in the same old config file:

$ sudo vim /etc/nginx/sites-enabled/flask_aws

Add the following in the file:

server {
listen 80;
server_name <EC2 Public IP instance>;
location / {
proxy_pass http://unix:/home/ubuntu/flask_aws/flask_aws.sock;
}
}

server {
listen 8080;
server_name <EC2 Public IP instance>;
location / {
proxy_pass http://unix:/home/ubuntu/flask_aws1/flask_aws.sock;
}
}

Note: Make sure that the new ports are added to the EC2 security groups for it to load on the browser

Configure the gunicorn service settings:

$ sudo vim /etc/systemd/system/flask_aws1.service

Add the following content:

[Unit]Description=AWS Flask multiple apps deploymentAfter=network.target[Service]User=ubuntuGroup=www-dataWorkingDirectory=/home/ubuntu/flask_aws1ExecStart=/usr/bin/gunicorn3 —-workers 3 --bind unix:flask_aws.sock -m 007 app:app

Note that it points to the same sock file.

The final directory structures:

Flask App 1 directory structure
Flask App 2 directory structure

Finally, restart both the daemon, nginx and the gunicorn services

$ sudo systemctl daemon-reload
$ sudo service nginx restart
$ sudo service flask_aws restart
$ sudo service flask_aws1 restart

Check the status of the applications running:

$ sudo service flask_aws status
$ sudo service flask_aws1 status

BINGO! This is what the final output looks like on different ports (80 and 8080):

Flask App 1:

Flask App 1 output on port 80

Flask App 2 :

Flask App 2 output on port 8080

For debugging:

$ sudo service flask_aws status
$ sudo service flask_aws1 status
$ sudo tail -30 /var/log/nginx/error.log

Thanks for reading this :D

Let me know if you have any questions!

References:

https://www.youtube.com/watch?v=-Gc8CMjQZfc&list=PL5KTLzN85O4KTCYzsWZPTP0BfRj6I_yUP&index=1
https://twitter.com/nginx
https://www.youtube.com/watch?v=dVEjSmKFUVI

--

--