BOBOBK

Deploy Flask Python Web Service in Production Environment Using Gunicorn

MISCELLANEOUS

Today I logged into the server and found python using a very high percentage of CPU, then discovered it was caused by some small web tools made with Flask on this site. Finally understood why Flask warns not to deploy directly in production. 0-0.
So I decided to properly deploy Flask in a production environment. Since most people highly recommend gunicorn and it’s easy to configure, this article also uses gunicorn to deploy Flask in production.

1. Install gunicorn

You can install it directly using pip.

pip install gunicorn  

2. Start Flask app with gunicorn command

Here is the command to start gunicorn in the background:

gunicorn -w 4 flaskr:application --bind=127.0.0.1:5000 --daemon  
  • -w 4: specifies 4 worker processes
  • --bind=: specifies the working port, here the same as dev mode port 5000
  • --daemon: run in background

"flaskr:application": here flaskr is the filename, application is the app name
Of course, gunicorn has many other configurations, but since we use nginx as a reverse proxy, these settings are enough.

3. Flask example

No explanation can replace a solid example.
Filename: flaskr.py

from flask import Flask, redirect  
from flask import request  
from flask import render_template  
import os

def create_app(test_config=None):  
    # create and configure the app  
    app = Flask(__name__, instance_relative_config=True)  
    app.config.from_mapping(  
        SECRET_KEY='production',  
        DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),  
    )  

    if test_config is None:  
        # load the instance config, if it exists, when not testing  
        app.config.from_pyfile('config.py', silent=True)  
    else:  
        # load the test config if passed in  
        app.config.from_mapping(test_config)  

    # ensure the instance folder exists  
    try:  
        os.makedirs(app.instance_path)  
    except OSError:  
        pass  

    # a simple page that says hello  
    @app.route('/')  
    def hello_world():  
        return 'Hello, World!'  

    return app  

application = create_app()  

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

After running the gunicorn command above, test with:

wget 127.0.0.1:5000  

If it returns “Hello, World!”, the configuration was successful.

4. Nginx reverse proxy to local Flask web app

Add proxy settings in nginx configuration file for the local Flask port:

server  
{  
    listen 80;  
    server_name 127.0.0.1; # Server public IP or domain  
    root /www/wwwroot/www.bobobk.com;  
    location / {  
        proxy_pass http://localhost:5000;  
        proxy_redirect off;  
        proxy_set_header Host $host;  
    }  
}  

This completes the whole process of configuring Flask in production with gunicorn. Now let’s check the resource usage.

top  

You can see that after using production configuration, Flask’s CPU usage dropped rapidly. This is very important for low-spec cloud servers. Now my 1GB memory server can run smoothly again…

Related