Gunicorn (Green Unicorn) is a Python WSGI HTTP Server for production.
Basic Setup
bash# Install pip install gunicorn # Run gunicorn myproject.wsgi:application # With options gunicorn myproject.wsgi:application \ --bind 0.0.0.0:8000 \ --workers 4
Configuration File
python# gunicorn.conf.py import multiprocessing # Server socket bind = '0.0.0.0:8000' backlog = 2048 # Worker processes workers = multiprocessing.cpu_count() * 2 + 1 worker_class = 'sync' worker_connections = 1000 timeout = 30 keepalive = 2 # Process naming proc_name = 'myproject' # Logging accesslog = '-' # stdout errorlog = '-' # stderr loglevel = 'info' access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' # Security limit_request_line = 4094 limit_request_fields = 100 limit_request_field_size = 8190
bash# Run with config file gunicorn myproject.wsgi:application -c gunicorn.conf.py
Worker Types
python# gunicorn.conf.py # Sync workers (default) - Good for CPU-bound worker_class = 'sync' workers = (multiprocessing.cpu_count() * 2) + 1 # Async workers with gevent - Good for I/O-bound # pip install gevent worker_class = 'gevent' worker_connections = 1000 workers = multiprocessing.cpu_count() * 2 # Async workers with eventlet # pip install eventlet worker_class = 'eventlet' # Thread workers worker_class = 'gthread' threads = 4
Systemd Service
ini# /etc/systemd/system/gunicorn.service [Unit] Description=Gunicorn daemon for myproject After=network.target [Service] User=www-data Group=www-data WorkingDirectory=/var/www/myproject ExecStart=/var/www/myproject/venv/bin/gunicorn \ --access-logfile - \ --workers 4 \ --bind unix:/run/gunicorn/myproject.sock \ myproject.wsgi:application ExecReload=/bin/kill -s HUP $MAINPID RuntimeDirectory=gunicorn Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
bash# Enable and start sudo systemctl daemon-reload sudo systemctl enable gunicorn sudo systemctl start gunicorn sudo systemctl status gunicorn
Graceful Restarts
bash# Send HUP signal for graceful reload kill -HUP $(cat /run/gunicorn/gunicorn.pid) # Or via systemctl sudo systemctl reload gunicorn
Monitoring
python# gunicorn.conf.py # StatsD integration from gunicorn import instrument statsd_host = 'localhost:8125' statsd_prefix = 'myproject' # Custom hooks def on_starting(server): print('Starting Gunicorn server') def on_exit(server): print('Shutting down Gunicorn server') def worker_abort(worker): print(f'Worker {worker.pid} aborted')