Make Gunicorn respect config.json settings

- Updated gunicorn.conf.py to read host/port from config.json
- Added gunicorn section to config.json for server settings
- Created start_gunicorn.py as alternative launcher
- Updated config.json with server settings (127.0.0.1:6969)
- Updated documentation with new startup options
This commit is contained in:
2025-09-20 20:25:36 +01:00
parent 4b31d3b9e0
commit 720b89a296
4 changed files with 95 additions and 15 deletions

View File

@@ -35,7 +35,7 @@ python config_manager.py rate_limiting.endpoints.login "10 per minute"
## Running with Gunicorn (Production) ## Running with Gunicorn (Production)
### Quick Start ### Quick Start - Uses config.json settings
```bash ```bash
# Activate virtual environment # Activate virtual environment
source .venv/bin/activate source .venv/bin/activate
@@ -43,25 +43,28 @@ source .venv/bin/activate
# Install dependencies # Install dependencies
pip install -r requirements.txt pip install -r requirements.txt
# Run with Gunicorn (recommended for production) # Option 1: Run with config file (recommended - uses config.json)
gunicorn --config gunicorn.conf.py app:app gunicorn --config gunicorn.conf.py app:app
# Option 2: Run with Python launcher (also uses config.json)
python start_gunicorn.py
``` ```
### Alternative Gunicorn Commands ### Manual Gunicorn Commands (ignores config.json)
**Basic production run:** **Basic production run:**
```bash ```bash
gunicorn -w 4 -b 0.0.0.0:5050 app:app gunicorn -w 4 -b 127.0.0.1:6969 app:app
``` ```
**With more workers (for higher traffic):** **With more workers (for higher traffic):**
```bash ```bash
gunicorn -w 8 -b 0.0.0.0:5050 --timeout 30 app:app gunicorn -w 8 -b 127.0.0.1:6969 --timeout 30 app:app
``` ```
**Behind a reverse proxy (nginx/apache):** **Behind a reverse proxy (nginx/apache):**
```bash ```bash
gunicorn -w 4 -b 127.0.0.1:5050 app:app gunicorn -w 4 -b 127.0.0.1:6969 app:app
``` ```
### Environment Variables for Production ### Environment Variables for Production

View File

@@ -1,10 +1,17 @@
{ {
"app": { "app": {
"name": "ircquotes", "name": "ircquotes",
"host": "0.0.0.0", "host": "127.0.0.1",
"port": 5050, "port": 6969,
"debug": false "debug": false
}, },
"gunicorn": {
"workers": 4,
"timeout": 30,
"keepalive": 5,
"max_requests": 1000,
"preload": true
},
"database": { "database": {
"uri": "sqlite:///quotes.db?timeout=20", "uri": "sqlite:///quotes.db?timeout=20",
"pool_timeout": 20, "pool_timeout": 20,

View File

@@ -1,21 +1,42 @@
# Gunicorn configuration file for ircquotes # Gunicorn configuration file for ircquotes
import multiprocessing import multiprocessing
import json
import os
# Server socket # Load configuration from config.json
bind = "0.0.0.0:5050" def load_app_config():
config_file = os.path.join(os.path.dirname(__file__), 'config.json')
try:
with open(config_file, 'r') as f:
return json.load(f)
except:
# Fallback to defaults if config.json not found
return {
"app": {"host": "0.0.0.0", "port": 5050}
}
app_config = load_app_config()
# Server socket - use config.json values
host = app_config.get('app', {}).get('host', '0.0.0.0')
port = app_config.get('app', {}).get('port', 5050)
bind = f"{host}:{port}"
backlog = 2048 backlog = 2048
# Worker processes # Worker processes - use config.json values
workers = multiprocessing.cpu_count() * 2 + 1 workers = app_config.get('gunicorn', {}).get('workers', multiprocessing.cpu_count() * 2 + 1)
worker_class = "sync" worker_class = "sync"
worker_connections = 1000 worker_connections = 1000
timeout = 30 timeout = app_config.get('gunicorn', {}).get('timeout', 30)
keepalive = 5 keepalive = app_config.get('gunicorn', {}).get('keepalive', 5)
# Restart workers after this many requests, to help prevent memory leaks # Restart workers after this many requests, to help prevent memory leaks
max_requests = 1000 max_requests = app_config.get('gunicorn', {}).get('max_requests', 1000)
max_requests_jitter = 100 max_requests_jitter = 100
# Preload app for better performance
preload_app = app_config.get('gunicorn', {}).get('preload', True)
# Logging # Logging
accesslog = "-" # Log to stdout accesslog = "-" # Log to stdout
errorlog = "-" # Log to stderr errorlog = "-" # Log to stderr

49
start_gunicorn.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
Gunicorn launcher that reads configuration from config.json
"""
import json
import subprocess
import sys
from config_loader import config
def main():
"""Launch Gunicorn with settings from config.json"""
# Get configuration values
host = config.app_host
port = config.app_port
workers = config.get('gunicorn.workers', 4)
# Build Gunicorn command
cmd = [
'gunicorn',
'--bind', f'{host}:{port}',
'--workers', str(workers),
'--timeout', '30',
'--keepalive', '5',
'--max-requests', '1000',
'--max-requests-jitter', '100',
'--access-logfile', '-',
'--error-logfile', '-',
'--log-level', 'info',
'--preload',
'app:app'
]
print(f"Starting Gunicorn on {host}:{port} with {workers} workers...")
print(f"Command: {' '.join(cmd)}")
# Execute Gunicorn
try:
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
print(f"Error starting Gunicorn: {e}")
sys.exit(1)
except KeyboardInterrupt:
print("\nStopping Gunicorn...")
sys.exit(0)
if __name__ == "__main__":
main()