loading...
Cover image for Deploy Flask App - Complete information and Samples

Deploy Flask App - Complete information and Samples

sm0ke profile image Sm0ke ・7 min read

Hello Coders,

This article explains how to Deploy Flask in production using multiple configurations (Nginx/Gunicorn, Nginx/Waitress, Docker), and different sample apps. The concepts can be adapted with a minimum effort also on Django, the Flask's big brother.


Thank you for reading! My (nick)name is Sm0ke and I've built AppSeed, a platform used by 2.1k developers.


What is Deployment

Software deployment is all of the activities that make a software system available for use. Most of the time, developers code their apps using a workstation and later publish the product on a public domain/subdomain to be used by end-users. The process of making the software available for production use is called deployment.


What is Flask

For newcomers, Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications.
Classified as a microframework, Flask is written in Python and it does not require particular tools or libraries. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions.

WSGI (Web Server Gateway Interface) it is just an interface specification by which server and application communicate.

Flask, for instance, implements this communication protocol under the hood and let us code the upper level of our web app (features, login, database information manipulation).


WSGI Simple App (no Flask)

Probably the most simple WSGI app ever coded is this one:

def app(environ, start_response):
    data = b"Hello! This is a simple WSGI web app.\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])

Please save this code snippet in a file named myapp.py (or choose another name). We will refer this file in the next section.

This code snippet defines a method named app (we can choose another name) that returns a simple string Hello! This is a simple WSGI web app

The syntax used to define the method and the response pattern is defined in the WSGI protocol, section The Application/Framework Side.

On the other side, the server should also respect the WSGI protocol and implement The Server/Gateway Side.

This complex part is handled by Flask, Gunicorn, uWSGI, and all other WSGI-ready servers that we can use in production.


Gunicorn

At this point, we have a super simple WSGI app that echos a Hello world! .. and that's all. To see the message in the browser we need a WSGI server (Gunicorn) able to execute our app and serve browser request.

Install Gunicorn

The most convenient way is to use PIP, the official package manager for Python.

$ pip install gunicorn

Once the Gunicorn is available we can execute our simple app.

$ gunicorn myapp:app

Gunicorn being a WSGI server, expect the WSGI object to execute as argument, witch in our case is defined in myapp.py file in method app.


By default Gunicorn starts on port 8000. To use another port, use -b argument (b comes from bind).

$ gunicorn myapp:app -b :8001

The Browser effect

Gunicorn - start App


Waitress

Gunicorn is for sure an amazing server that we can use without issues on production .. but has a small limitation. Cannot be used on windows stations. This problem is solved by Waitress, a powerful WSGI-ready server.

Install waitress

$ pip install waitress

We can execute our simple WSGI app under waitress using a single line:

$ waitress-serve myapp:app 

By default, waitress starts on port 8080, but we can adjust the port using --port argument:

$ waitress-serve --port=8000 myapp:app

That was pretty simple, right?


WSGI App - Flask version

If we take a second look at myapp.py, we can see that our code delivers only a simple text and nothing else. How about setting a database, a fancy UI, some forms, security maybe?

Well, using Flask we can re-use many modules and features coded by open-source enthusiasts across the globe.

Before using Flask, we need to install it. PIP comes to the rescue:

$ pip install flask

A super simple (WSGI) Flask app might be this one:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello WSGI ... from Flask!'

Save the content as flask_app.py for later reference.

flask_app.py does the following:

  • Import the Flask module
  • Defines the WSGI object with the name app
  • Define a default route that returns a simple string

Execute with Gunicorn

$ gunicorn flask_app:app
[3445] [INFO] Starting gunicorn 19.10.0
[3445] [INFO] Listening at: http://127.0.0.1:8000 (3445)
[3445] [INFO] Using worker: sync
[3449] [INFO] Booting worker with pid: 3449

The Browser effect

Gunicorn - execute Flask app.


Execute using waitress is super simple. We need to write just a single line:

$ waitress-serve --port=8000 flask_app:app

If we visit the app in the browser, we should see the same dummy message Hello WSGI ... from Flask!.


Nginx

At this point, we are able to start the app using Gunicorn and Waitress but the production environment requires a secure HTTPS connection, the recommended way to expose services in current times. To achieve this, we need a proxy server configured in front of Gunicorn/Waitress to secure the connection with the browser. Nginx can be used as reverse-proxy.

For newcomers, A reverse proxy is a server that sits in front of web servers and forwards client (e.g. web browser) requests to those web servers. Reverse proxies are typically implemented to help increase security, performance, and reliability.

Cloudfare provides a good intro to this useful concept - What Is A Reverse Proxy.

Forward proxy flow - Reverse proxy architecture.


How to set up Nginx

Before using Nginx, we need to install it. If your production server uses Ubuntu, here is the magic line:

$ sudo apt install nginx

On CentOS servers, the syntax is slightly different:

$ sudo yum install epel-release
$ sudo yum install nginx

Start the Nginx server

$ systemctl status nginx

Nginx now serves a welcome page, and we need to add a simple configuration to link the default port 80 to forward the requests back & fort to our WSGI app.

If we assume that WSGI app runs on port 8000 using Gunicorn or Waitress, Nginx must be configured to bind that address. We can do this with ease, by editing a single file.

$ vi /etc/nginx/sites-enabled/default  [On Debian/Ubuntu]
$ vi /etc/nginx/nginx.conf             [On CentOS/RHEL]

Before editing anything, is recommended to backup the current file, in case something is not configured properly. Once we did this, the file should contain the following snippet:

server {
    listen      80;
    server_name www.my-domain.com;

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

To load this new configuration, we need to restart Nginx:

$ sudo systemctl reload nginx

By accessing the port 80 in the browser, we should see the same message previously served by the WSGI apps.


With all those concepts understood, we can move further with this presentation and mention a few starters already configured for Nginx/Gunicorn, HEROKU, and Docker.
In case you have issues using the samples, just drop any questions in the comments area or join the AppSeed Discord server and ask for help.


Flask Dashboard - Black Design

Open-Source admin dashboard coded in Flask Framework - Features:

  • LIVE Demo
  • Product Page
  • DBMS: SQLite, PostgreSQL (production)
  • DB Tools: SQLAlchemy ORM, Alembic (schema migrations)
  • Modular design with Blueprints
  • Session-Based authentication (via flask_login), Forms validation
  • Deployment scripts: Docker, Gunicorn / Nginx, Heroku

Flask Dashboard - Black Design, dashboard screen.


Flask Dashboard Datta Able

Open-Source admin dashboard coded in Flask Framework - Features:

  • LIVE Demo
  • Product Page
  • DBMS: SQLite, PostgreSQL (production)
  • DB Tools: SQLAlchemy ORM, Alembic (schema migrations)
  • Modular design with Blueprints
  • Session-Based authentication (via flask_login), Forms validation
  • Deployment scripts: Docker, Gunicorn / Nginx, Heroku

Flask Dashboard DattaAble - Starter project coded in Flask.


Flask Corona Dark

Open-Source admin dashboard coded in Flask Framework - Features:

  • LIVE Demo
  • Product Page
  • DBMS: SQLite, PostgreSQL (production)
  • DB Tools: SQLAlchemy ORM, Alembic (schema migrations)
  • Modular design with Blueprints
  • Session-Based authentication (via flask_login), Forms validation
  • Deployment scripts: Docker, Gunicorn / Nginx, Heroku

Flask Dashboard Corona Dark - Open-Source template project provided by AppSeed.


Flask Atlantis Dark

Open-Source admin dashboard coded in Flask Framework - Features:

  • LIVE Demo
  • Product Page
  • DBMS: SQLite, PostgreSQL (production)
  • DB Tools: SQLAlchemy ORM, Alembic (schema migrations)
  • Modular design with Blueprints
  • Session-Based authentication (via flask_login), Forms validation
  • Deployment scripts: Docker, Gunicorn / Nginx, Heroku

Flask Dashboard Atlantis Dark - Starter project coded in Flask.


Flask Dashboard CoreUI

CoreUI is an Open Source Bootstrap Admin Template. But CoreUI is not just another Admin Template. It goes way beyond hitherto admin templates thanks to transparent code and file structure. And if that's not enough, let’s just add that CoreUI consists bunch of unique features and over 1000 high-quality icons.

  • LIVE Demo
  • Product Page
  • DBMS: SQLite, PostgreSQL (production)
  • DB Tools: SQLAlchemy ORM, Alembic (schema migrations)
  • Modular design with Blueprints
  • Session-Based authentication (via flask_login), Forms validation
  • Deployment scripts: Docker, Gunicorn / Nginx, Heroku

Flask Dashboard CoreUI - Template project provided by AppSeed.


Thank you for reading! Let me know your thoughts in the comments.


Resources

Posted on by:

sm0ke profile

Sm0ke

@sm0ke

#Automation, my favorite programming language

Discussion

pic
Editor guide
 

Nice intro! How about setting up SSL in that Nginx?

 

Hello!
Digital Ocean has a nice tutorial on this point, using self-signed certs.

Create a Self-Signed SSL Certificate for Nginx on CentOS 7

By using the console, via OpenSSL, the certs can be easily created.
Once you have the certificate and private key, the Nginx should be configured to use them.

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name server_IP_address;

    ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
}
 

Sounds like an easy set up! Thank you!

 

Great List.πŸ‘

 

Thank you!