How to deploy a Flask app with gunicorn or waitress
Run a Flask app in production on Schokr using gunicorn or waitress instead of the dev server, bound to 0.0.0.0 and your allocated port.
Updated · 2 min read
Do not run Flask's built-in development server in production. On Schokr, serve your Flask app with a production WSGI server such as gunicorn or waitress, bound to 0.0.0.0 and the port shown in your server's Network section.
1. Your Flask app
app.py:
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/")
def index():
return jsonify(status="ok")
requirements.txt:
flask==3.0.3
gunicorn==23.0.0
2. Option A: gunicorn
gunicorn is the most common choice on Linux:
gunicorn --bind 0.0.0.0:25571 --workers 2 app:app
app:app means "the app object inside app.py". Replace 25571 with your port. Each worker is a separate process with its own memory, so start with 2 workers on a small server and increase only if you have memory to spare.
2. Option B: waitress from a Python file
If your template runs a Python file rather than a custom command, waitress lets you start the server from code. Add waitress to requirements.txt and create main.py:
import os
from waitress import serve
from app import app
port = int(os.environ.get("APP_PORT", "8080"))
serve(app, host="0.0.0.0", port=port, threads=4)
Then set main.py as the file to run.
3. Deploy on Schokr
- Create a server with the Python template in the console. 256 to 512 MB is fine for most Flask apps.
- Note your port in the Network section.
- Upload
app.py,requirements.txtand yourtemplates/andstatic/folders with the file manager. Do not upload your local venv. - In your server's Startup settings, set the file to run (for waitress) or the startup command (for gunicorn), depending on what the template exposes.
- Start the server. pip installs your requirements, then the server starts.
- Visit
http://<server-address>:<port>.
Settings and secrets
Set SECRET_KEY from the environment rather than in code:
import os
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]
See environment variables and secrets for using a .env file.
Behind a proxy
If you put Cloudflare or another proxy in front, use ProxyFix so Flask sees the real scheme and client IP:
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
Troubleshooting
| Problem | Fix |
|---|---|
Running on http://127.0.0.1:5000 in the log | You are running the dev server. Switch to gunicorn or waitress. |
ModuleNotFoundError: No module named 'app' | The working directory or module path is wrong. See module not found. |
Worker killed, SIGKILL | Out of memory. Reduce workers or add memory. |
| Browser cannot connect | Check the bind address and port. See app not reachable. |