Deploy a Flask Application Using Gunicorn and Nginx

Gunicorn, What is it and why do I need it?

Gunicorn or ‘Green Unicorn’ is a Python WSGI HTTP Server for UNIX. It’s a pre-fork worker model.

By default python can not handle multiple requests at a time. Whenever you write a web application it is likely that multiple people will access it at the same time, which means that the server must serve multiple requests at a time. The webservers like Apache and Nginx can do that.

Now to deploy a python web application with a web server like nginx, there are tools like gunicorn, mod_wsgi, mod_uwsgi etc. What Gunicorn does is it uses Nginx as a proxy and to process the requests it spawns multiple worker processes and incoming requests are forwarded to them.

How it works is described in this answer on serverflault by Paul Davis who is the author of gunicorn.

Nginx will receive the request and if it's a dynamic request (generally based on URL patterns) then it will give that request to Gunicorn, which will process it, and then return a response to Nginx which then forwards the response back to the original client.

Ok, so let’s get started.

Let’s say your flask application looks like:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World"

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

and you run it like:

$ python main.py

To use gunicorn with this application, you need to install gunicorn. It is recommended that you install it from pypi that way you will get the latest stable version.

To install Gunicorn run:

$ pip install gunicorn

The next step is to run the application defined in your main.py using Gunicorn. Now in order to do that, you will have to create wsgi.py file which will contain the code like following.

from main import app

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

Here we just imported the application app from main.py and we are calling it’s run().

To run the application using gunicorn

$ gunicorn wsgi:app -b <host>:<port>

For example

$ gunicorn wsgi:app -b localhost:5000

If you want to configure number of workers,

gunicorn wsgi:app -b localhost:5000 --workers=2

When you specify --workers argument, that many processes are spawned. For example in the above case two worker processes are spawned.

This is the first part of deploying your flask application. In the second part let’s put this behind an Nginx server.

To use gunicorn with nginx you have to change the config files for your site in the /etc/nginx/stes-available/<your-site> and /etc/nginx/sites-enabled/<your-site> directories.

The config looks like:

server {
    listen       80;
    server_name  your_public_dnsname_here;

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

Once this is done restart Nginx

$ sudo nginx -t # this is used to check the syntax errors in the nginx config.
$ sudo systemctl restart nginx

Once you restart the nginx service, you will be able to access your flask applicaton from your browser.

In this way you can deploy your flask application with Gunicorn and Nginx.

There are few more things which are important such as to create a service for this flask applcation, using a socket file instead of using the port in the nginx config etc. this post will be helpful for all of those things.