Gunicorn Python app server
Light · Postcard
102 × 152 mm · PDF
Dark · Postcard
102 × 152 mm · PDF
Ink saver · Postcard
102 × 152 mm · PDF
Light · A4 landscape
297 × 210 mm · PDF
Dark · A4 landscape
297 × 210 mm · PDF
Ink saver · A4 landscape
297 × 210 mm · PDF
Light · A3 landscape
420 × 297 mm · PDF
Dark · A3 landscape
420 × 297 mm · PDF
Ink saver · A3 landscape
420 × 297 mm · PDF
Start here
gunicorn app:app
gunicorn -w 4 app:app
gunicorn -b 0.0.0.0:8000 app:app
gunicorn --reload app:app
gunicorn -c gunicorn.conf.py app:app
gunicorn --access-logfile - app:app
gunicorn -t 60 app:app
kill -HUP <pid>
Concepts
- Client browser
- nginx TLS, static
- Master gunicorn, no requests
- Workers run your app
Run
gunicorn <module>:<app>
gunicorn '<module>:<factory>()'
gunicorn -w <n> <module>:<app>
gunicorn -b <host>:<port>
<module>:<app>
gunicorn -b unix:<path>
<module>:<app>
gunicorn <project>.wsgi
gunicorn --reload <module>:<app>
gunicorn --check-config <module>:<app>
gunicorn --print-config <module>:<app>
gunicorn --chdir <dir>
<module>:<app>
gunicorn --pythonpath <dirs>
<module>:<app>
gunicorn -e <KEY>=<value>
<module>:<app>
gunicorn --paste <file.ini>
gunicorn -vGUNICORN_CMD_ARGS="--bind=:8000 -w 4"
Workers
-k sync-k gthread --threads <n>
-k gevent-k asgi--worker-connections <n>
--max-requests <n>
--max-requests-jitter <n>
-t <sec> / --timeout <sec>
--graceful-timeout <sec>
--preload--worker-tmp-dir /dev/shm
-u <user> -g <group>
-p <file>| Class | Fits |
|---|---|
sync |
simple CPU-bound apps |
gthread |
mixed or blocking I/O |
gevent |
many slow connections |
asgi |
async frameworks |
Logging
--access-logfile -
--error-logfile -
--log-level <level>
--access-logformat "<fmt>"
--capture-output
--log-config <file>
--statsd-host <host:port>
-n <name>Signals
kill -HUP <master-pid>
kill -TERM <master-pid>
kill -INT <master-pid>
kill -TTIN <master-pid>
kill -TTOU <master-pid>
kill -USR1 <master-pid>
kill -USR2 <master-pid>
kill -WINCH <master-pid>
- USR2 new master starts
- Old workers stop old master idles
- Old master exits new one serves
Config file
bind = "127.0.0.1:8000"workers = 4worker_class = "gthread"threads = 2timeout = 30accesslog = "-"errorlog = "-"preload_app = Truemax_requests = 1000
-c python:<module>
def when_ready(server): print("ready")def post_fork(server, worker): pass
Deploy
[Service]User=www-dataWorkingDirectory=/srv/appExecStart=/srv/app/.venv/bin/gunicorn -c gunicorn.conf.py app:appExecReload=/bin/kill -s HUP $MAINPIDRestart=on-failure
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr;}
--forwarded-allow-ips <ips>
--keyfile <key> --certfile <crt>
Recipes
gunicorn -w 4 -k gthread --threads 2 \ -b unix:/run/app.sock \ --access-logfile - --max-requests 1000 \ app:app
kill -HUP $(cat app.pid)# new code only if not --preload
kill -TTIN $(cat app.pid) # +1kill -TTOU $(cat app.pid) # -1
gunicorn --log-level debug -w 1 -t 0 \ --access-logfile - app:app



