Are a WSGI server and HTTP server required to serve a Flask app?

Setting up Flask with uWSGI and Nginx can be difficult. I tried following this DigitalOcean tutorial and still had trouble. Even with buildout scripts it takes time, and I need to write instructions to follow next time.

If I don't expect a lot of traffic, or the app is private, does it make sense to run it without uWSGI? Flask can listen to a port. Can Nginx just forward requests?

Does it make sense to not use Nginx either, just running bare Flask app on a port?


Solution 1:

When you "run Flask" you are actually running Werkzeug's development WSGI server, and passing your Flask app as the WSGI callable.

The development server is not intended for use in production. It is not designed to be particularly efficient, stable, or secure. It does not support all the possible features of a HTTP server.

Replace the Werkzeug dev server with a production-ready WSGI server such as Gunicorn or uWSGI when moving to production, no matter where the app will be available.


The answer is similar for "should I use a web server". WSGI servers happen to have HTTP servers but they will not be as good as a dedicated production HTTP server (Nginx, Apache, etc.).


Flask documents how to deploy in various ways. Many hosting providers also have documentation about deploying Python or Flask.

Solution 2:

First create the app:

import flask

app = flask.Flask(__name__)

Then set up the routes, and then when you want to start the app:

import gevent.pywsgi

app_server = gevent.pywsgi.WSGIServer((host, port), app)
app_server.serve_forever()

Call this script to run the application rather than having to tell gunicorn or uWSGI to run it.

I wanted the utility of Flask to build a web application, but had trouble composing it with other elements. I eventually found that gevent.pywsgi.WSGIServer was what I needed. After the call to app_server.serve_forever(), call app_server.stop() when to exit the application.

In my deployment, my application is listening on localhost:port using Flask and gevent, and then I have Nginx reverse-proxying HTTPS requests to it.