Add Docker support: Dockerfile, docker-compose.yml, and production configuration

- Add Dockerfile with multi-stage build for Flask app containerization
- Include .dockerignore to optimize build context
- Add docker-compose.yml for easy deployment with health checks
- Update run.py to handle production mode with allow_unsafe_werkzeug
- Add DOCKER.md with comprehensive deployment instructions
- Configure health check endpoint at /health
- Run as non-root user for security
- Support for environment variables and proper port mapping
This commit is contained in:
2025-08-24 19:20:38 +02:00
parent 26c82959a2
commit bec913a599
5 changed files with 205 additions and 1 deletions

59
.dockerignore Normal file
View File

@@ -0,0 +1,59 @@
# Git
.git
.gitignore
# Python
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env
pip-log.txt
pip-delete-this-directory.txt
.tox
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.log
.git
.mypy_cache
.pytest_cache
.hypothesis
# Virtual environments
.venv
venv/
ENV/
env/
.env
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Docker
Dockerfile
.dockerignore
# Documentation
README.md
*.md
# Qoder IDE
.qoder/

68
DOCKER.md Normal file
View File

@@ -0,0 +1,68 @@
# Docker Deployment for Markov Economics Simulation
This directory contains Docker configuration files for containerizing the Markov Economics Simulation App.
## Files
- `Dockerfile` - Multi-stage Docker build configuration
- `docker-compose.yml` - Docker Compose configuration for easy deployment
- `.dockerignore` - Files to exclude from Docker build context
## Quick Start
### Using Docker Compose (Recommended)
```bash
# Build and start the application
docker-compose up --build
# Run in detached mode
docker-compose up -d --build
# Stop the application
docker-compose down
```
### Using Docker directly
```bash
# Build the image
docker build -t markov-economics .
# Run the container
docker run -p 5000:5000 markov-economics
# Run with environment variables
docker run -p 5000:5000 \
-e FLASK_ENV=production \
-e FLASK_APP=run.py \
markov-economics
```
## Access
Once running, the application will be available at:
- Main application: http://localhost:5000
- Health check: http://localhost:5000/health
## Configuration
### Environment Variables
- `FLASK_ENV` - Flask environment (development/production)
- `FLASK_APP` - Entry point file (run.py)
- `PYTHONUNBUFFERED` - Ensure Python output is not buffered
### Ports
- `5000` - Main application port (Flask + SocketIO)
## Health Check
The container includes a health check that verifies the application is responding correctly at `/health`.
## Security
- Runs as non-root user (`appuser`)
- Uses Python slim base image
- Excludes development files via `.dockerignore`

40
Dockerfile Normal file
View File

@@ -0,0 +1,40 @@
# Use Python 3.12 slim image as base
FROM python:3.12-slim
# Set working directory
WORKDIR /app
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV FLASK_APP=run.py
ENV FLASK_ENV=production
# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements first for better caching
COPY requirements.txt .
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the application code
COPY . .
# Create a non-root user
RUN adduser --disabled-password --gecos '' appuser && \
chown -R appuser:appuser /app
USER appuser
# Expose the port the app runs on
EXPOSE 5000
# Health check
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
# Run the application
CMD ["python", "run.py"]

31
docker-compose.yml Normal file
View File

@@ -0,0 +1,31 @@
version: '3.8'
services:
markov-economics:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
- FLASK_APP=run.py
- PYTHONUNBUFFERED=1
volumes:
# Optional: Mount for persistent data if needed
- ./data:/app/data
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:5000/health', timeout=2)"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- markov-network
networks:
markov-network:
driver: bridge
volumes:
markov-data:
driver: local

8
run.py
View File

@@ -11,4 +11,10 @@ config_name = os.getenv('FLASK_CONFIG', 'development')
app = create_app(config_name)
if __name__ == '__main__':
socketio.run(app, debug=True, host='0.0.0.0', port=5000)
debug_mode = os.getenv('FLASK_ENV', 'development') == 'development'
# For production deployment, allow unsafe werkzeug or use a proper WSGI server
if os.getenv('FLASK_ENV') == 'production':
socketio.run(app, debug=False, host='0.0.0.0', port=5000, allow_unsafe_werkzeug=True)
else:
socketio.run(app, debug=debug_mode, host='0.0.0.0', port=5000)