Configure Docker to use Gunicorn instead of Flask development server for production deployment. Updated SocketIO configuration for gevent compatibility.
This commit is contained in:
@@ -36,5 +36,5 @@ EXPOSE 5000
|
|||||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
CMD python -c "import requests; requests.get('http://localhost:5000/health', timeout=2)" || exit 1
|
CMD python -c "import requests; requests.get('http://localhost:5000/health', timeout=2)" || exit 1
|
||||||
|
|
||||||
# Run the application
|
# Run the application with Gunicorn using gevent workers for SocketIO compatibility
|
||||||
CMD ["python", "run.py"]
|
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--worker-class", "gevent", "--worker-connections", "1000", "--timeout", "30", "wsgi:app"]
|
@@ -12,9 +12,10 @@ from config import config
|
|||||||
from app.models import SimulationManager
|
from app.models import SimulationManager
|
||||||
|
|
||||||
# Initialize SocketIO with enhanced proxy support
|
# Initialize SocketIO with enhanced proxy support
|
||||||
|
# For Gunicorn compatibility, we need to set the async_mode to 'gevent'
|
||||||
socketio = SocketIO(
|
socketio = SocketIO(
|
||||||
cors_allowed_origins="*",
|
cors_allowed_origins="*",
|
||||||
async_mode='threading',
|
async_mode='gevent' if os.getenv('FLASK_ENV') == 'production' else 'threading',
|
||||||
logger=False, # Disable to avoid log spam in production
|
logger=False, # Disable to avoid log spam in production
|
||||||
engineio_logger=False,
|
engineio_logger=False,
|
||||||
# Transport order: try websocket first, then polling
|
# Transport order: try websocket first, then polling
|
||||||
@@ -54,7 +55,7 @@ def create_app(config_name=None):
|
|||||||
# Initialize extensions with proxy-friendly settings
|
# Initialize extensions with proxy-friendly settings
|
||||||
socketio.init_app(
|
socketio.init_app(
|
||||||
app,
|
app,
|
||||||
async_mode='threading',
|
async_mode='gevent' if config_name == 'production' else 'threading',
|
||||||
cors_allowed_origins="*",
|
cors_allowed_origins="*",
|
||||||
allow_upgrades=True,
|
allow_upgrades=True,
|
||||||
transports=['websocket', 'polling'],
|
transports=['websocket', 'polling'],
|
||||||
|
@@ -3,3 +3,5 @@ Flask-SocketIO>=5.0.0
|
|||||||
numpy>=1.21.0
|
numpy>=1.21.0
|
||||||
matplotlib>=3.5.0
|
matplotlib>=3.5.0
|
||||||
plotly>=5.0.0
|
plotly>=5.0.0
|
||||||
|
gunicorn>=20.0.0
|
||||||
|
gevent>=21.0.0
|
5
run.py
5
run.py
@@ -15,8 +15,11 @@ if __name__ == '__main__':
|
|||||||
debug_mode = config_name == 'development'
|
debug_mode = config_name == 'development'
|
||||||
port = int(os.getenv('PORT', 5000)) # Use PORT env var or default to 5000
|
port = int(os.getenv('PORT', 5000)) # Use PORT env var or default to 5000
|
||||||
|
|
||||||
# For production deployment, allow unsafe werkzeug or use a proper WSGI server
|
# For production deployment with Gunicorn, SocketIO will be handled by Gunicorn
|
||||||
|
# For development, we use SocketIO's built-in server
|
||||||
if config_name == 'production':
|
if config_name == 'production':
|
||||||
|
# In production, Gunicorn will handle the server
|
||||||
|
# This is just a fallback
|
||||||
socketio.run(app, debug=False, host='0.0.0.0', port=port, allow_unsafe_werkzeug=True)
|
socketio.run(app, debug=False, host='0.0.0.0', port=port, allow_unsafe_werkzeug=True)
|
||||||
else:
|
else:
|
||||||
socketio.run(app, debug=debug_mode, host='0.0.0.0', port=port)
|
socketio.run(app, debug=debug_mode, host='0.0.0.0', port=port)
|
16
wsgi.py
Normal file
16
wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
WSGI entry point for the Markov Economics Flask application.
|
||||||
|
This file is used by Gunicorn to serve the application in production.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from app import create_app
|
||||||
|
|
||||||
|
# Use FLASK_ENV if set, otherwise default to production for Gunicorn
|
||||||
|
config_name = os.getenv('FLASK_ENV', 'production')
|
||||||
|
app = create_app(config_name)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# This is just for testing purposes
|
||||||
|
app.run()
|
Reference in New Issue
Block a user