How to make a Scalable Python Web App using Flask, Gunicorn, NGINX on Ubuntu 14.04

August 8, 2015

This article will cover creating a Scalable Python Web Application using Flask (microframework for Python) Gunicorn (Python WSGI HTTP Server for UNIX) and NGINX on Ubuntu 14.04. There are other more full featured Python web frameworks such as Django but if you need a light weight web app or API server this stack can be a nice solution.

Step 0
Time Matters!

sudo apt-get update
 
sudo ntpdate pool.ntp.org
 
sudo apt-get install ntp

Step 1
Install PIP

sudo apt-get install python-pip

Step 2
Install Python Development

sudo apt-get install python-dev

Step 3
Install Flask

sudo pip install Flask

Step 4
Install Gunicorn

sudo pip install gunicorn

Step 5
Create a Python Flask Application

cd ~
cd /home/ubuntu/FLASK
vim hello.py

hello.py

 
from flask import Flask
app = Flask(__name__)
 
@app.route("/")
def hello():
    return "Hello World!"
 
if __name__ == "__main__":
    app.run()

Step 6
Create a pre-fork Gunicorn startup script to run your Flask Application

cd /home/ubuntu/FLASK
vim gunicorn.sh

gunicorn.sh

#!/bin/bash
 
NAME="hello"
FLASKDIR=/home/ubuntu/FLASK
SOCKFILE=/home/ubuntu/FLASK/sock
USER=root
GROUP=root
NUM_WORKERS=3
 
echo "Starting $NAME"
 
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
 
# Start your gunicorn
exec gunicorn hello:app -b 0.0.0.0:8080 \
  --name $NAME \
  --workers $NUM_WORKERS \
  --user=$USER --group=$GROUP \
  --bind=unix:$SOCKFILE

Step 7
Create a Gunicorn upstart script

cd /etc/init/
sudo vim gunicorn.conf
 
#Upstart Script
 
description "gunicorn"
 
respawn
respawn limit 15 5
 
start on runlevel [2345]
stop on runlevel [06]
 
env SCRIPTS_BIN=/home/ubuntu/FLASK
 
script
chdir $SCRIPTS_BIN
exec ./gunicorn.sh
end script

Step 8
Install NGINX

sudo apt-get install nginx
cd /etc/nginx/conf.d/
mkdir /home/ubuntu/www
sudo vim flask.conf

flask.conf *Make sure you change the server_name

upstream gunicorn_server {
 
  server localhost:8080 fail_timeout=0;
}
 
    server {
        listen       80;
        server_name  your-web-app-hostname-here.com;
 
	root /home/ubuntu/www;
	client_max_body_size 4G;
	keepalive_timeout 5;
        proxy_read_timeout 900;
 
        location / {
	try_files $uri @app;
        }
 
	location @app {
      	 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Real-IP	$remote_addr;
      	 proxy_set_header Host $http_host;
      	 proxy_redirect off;
      	# pass to the upstream gunicorn server mentioned above 
	 proxy_pass http://gunicorn_server;
	}
 
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
   }

Step 9
Start Gunicorn and NGINX

sudo service gunicorn start
sudo service nginx restart

More Information:

  • The formula for how many Gunicorn workers to run should be (2 x $num_cores) + 1
  • There are different types of Gunicorn workers
  • You can configure threads in Gunicorn
  • If it applies you can configure NGINX Caching to help with performance
  • Leave a Reply