When using Flask + Gunicorn, is Werkzeug still used ?
Lets say I have a simple Flask app:
from flask import Flask
from flask.cli import FlaskGroup
def create_app():
app = Flask(__name__)
# Other inits here: DB, config etc.
return app
cli = FlaskGroup(
add_default_commands=True,
create_app=create_app
)
if __name__ == '__main__':
cli()
Then I can run my app via:
$ python3 app.py run
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
From what I understand, here Werkzeug is started as a WSGI server in front of my Flask app, as the run
command call Flask's run_command
which call Werkzeug run_simple
.
Now, as stated in both Flask documentation & Werkzeug documention:
Do not use this command to run your application in production. Only use the development server during development. The development server is provided for convenience, but is not designed to be particularly secure, stable, or efficient. See Deploying to Production for how to run in production.
I guess we are talking about Werkzeug here. So next I want to setup Gunicorn in front of my app (to keep this question as simple as possible I omit all possible gunicorn options here):
$ pip install gunicorn
$ gunicorn --bind 0.0.0.0:5000 app:cli
[2023-06-21 11:25:05 +0200] [79911] [INFO] Starting gunicorn 20.1.0
[2023-06-21 11:25:05 +0200] [79911] [INFO] Listening at: http://0.0.0.0:5000 (79911)
[2023-06-21 11:25:05 +0200] [79911] [INFO] Using worker: sync
[2023-06-21 11:25:05 +0200] [79959] [INFO] Booting worker with pid: 79959
Good, my app start. But Gunicorn still uses app:cli
as an entrypoint, which call the run
/run_command
/run_simple
described above.
So here is my question: is Werkzeug still used between Gunicorn and my Flask app ? If so it means 2 WSGI servers are "chaining" requests to my Flask app. Is there a way to get rid of it ? Or is it the way it is intended to be used ?
When you start Gunicorn with the command gunicorn --bind 0.0.0.0:5000 app:cli
, Gunicorn takes over as the WSGI server and handles the HTTP traffic. It loads your Flask application using the app:cli
entry point, but it does not use Werkzeug's development server in this case.
With gunicorn in place you are sure that you are not dealing with a double layer of servers.Gunicorn handles the HTTP server functionality and directly communicates with your Flask application, eliminating the need for Werkzeug in the production setup.