forked from eth-lre/math2visual
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
178 lines (171 loc) · 7.25 KB
/
docker-compose.yml
File metadata and controls
178 lines (171 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
services:
app:
build:
context: .
args:
VITE_ENABLE_ANALYTICS: ${VITE_ENABLE_ANALYTICS:-false}
image: math2visual:latest
container_name: math2visual
ports:
- "80:80"
- "443:443"
volumes:
# Mount Let's Encrypt certificates (read-only)
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
# Mount nginx.conf for easy updates without rebuilding
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
# Mount backend storage directory directly for persistence
# This allows user uploads and analytics to persist, and uses the existing backend/storage structure
- ./backend/storage:/app/storage
environment:
# Add your environment variables here
- OPENAI_API_KEY=
- GEMINI_API_KEY=
# ClamAV configuration (service name defined below)
- CLAMAV_HOST=clamav
- CLAMAV_PORT=3310
- SVG_STORAGE_MODE=local
- SVG_DATASET_PATH=/app/storage/datasets/svg_dataset
# Database configuration (PostgreSQL is always started for tutor sessions)
# Default DATABASE_URL connects to the postgres service
# To override, set DATABASE_URL in .env file or override inline
# Password is set via POSTGRES_PASSWORD environment variable (defaults to math2visual_password)
# Note: If you change POSTGRES_PASSWORD, also update DATABASE_URL to match
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-math2visual_password}
- DATABASE_URL=${DATABASE_URL:-postgresql://math2visual_user:math2visual_password@postgres:5432/math2visual_analytics}
- DATABASE_ECHO=false
# Flask environment (affects CORS and other behaviors)
- FLASK_ENV=production
# CORS configuration (optional - configure explicitly for production)
# Examples:
# - CORS_ORIGINS=https://your-frontend-domain.com,https://www.your-frontend-domain.com
# - FRONTEND_URL=https://your-frontend-domain.com
# Default: Uses production defaults (HTTPS localhost for development/testing)
- CORS_ORIGINS=${CORS_ORIGINS:-https://localhost:5173,https://127.0.0.1:5173}
- FRONTEND_URL=${FRONTEND_URL:-}
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "python3", "-c", "import socket; s = socket.socket(); s.settimeout(2); result = s.connect_ex(('127.0.0.1', 80)); s.close(); exit(0 if result == 0 else 1)"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# ClamAV antivirus service (used by backend via pyClamd)
clamav:
image: clamav/clamav:latest
container_name: math2visual-clamav
restart: unless-stopped
# ports:
# # Expose for debugging; app talks to it over the Docker network using CLAMAV_HOST/CLAMAV_PORT
# # - "3310:3310"
volumes:
# Persist virus database to avoid re-downloading on every restart
- clamav-db:/var/lib/clamav
environment:
# Allow reasonably large files/streams for scanning
- CLAMD_CONF_MaxFileSize=50M
- CLAMD_CONF_MaxScanSize=50M
- CLAMD_CONF_StreamMaxLength=50M
# Configure freshclam to check for updates every 2 hours (12 times per day)
# The official ClamAV image runs freshclam automatically in the background
- FRESHCLAM_CONF_Checks=12
# Update database on container start
- UPDATE=true
# PostgreSQL database (always started - required for tutor sessions and optional for analytics)
postgres:
image: postgres:16-alpine
container_name: math2visual-postgres
restart: unless-stopped
# ports:
# # Expose for debugging; app talks to it over the Docker network using DATABASE_URL
# # - "5432:5432"
volumes:
# Persist database data across container restarts
- postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=math2visual_analytics
- POSTGRES_USER=math2visual_user
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-math2visual_password}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U math2visual_user -d math2visual_analytics"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
# Certbot for initial certificate setup (run manually)
# Usage: docker-compose run --rm certbot-init certbot certonly --webroot -w /var/www/certbot -d your-domain.com --email your-email@example.com
certbot-init:
image: certbot/certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
# This service should be run manually, not started automatically
# Certbot for automatic renewal
certbot-renew:
image: certbot/certbot
container_name: certbot-renew
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet --deploy-hook \"docker exec math2visual nginx -s reload\"; sleep 12h & wait $${!}; done;'"
restart: unless-stopped
# Cleanup service for temporary files (runs via cron every hour)
# Note: This service uses a Docker Compose profile and will only start when explicitly enabled.
# When analytics is enabled (VITE_ENABLE_ANALYTICS=true), do NOT start this service,
# as it would delete tutor sessions that should be preserved for analytics.
#
# To start the cleanup service (when analytics is disabled):
# docker-compose --profile cleanup up -d
#
# To start without cleanup (when analytics is enabled):
# docker-compose up -d
cleanup:
profiles: ["cleanup"]
build:
context: .
args:
VITE_ENABLE_ANALYTICS: ${VITE_ENABLE_ANALYTICS:-false}
container_name: math2visual-cleanup
volumes:
- ./backend/storage:/app/storage
- ./cleanup-logs:/var/log
environment:
- CLEANUP_OUTPUT_AGE_HOURS=24
- CLEANUP_TEMP_SVG_AGE_HOURS=1
- DATABASE_URL=${DATABASE_URL:-}
# Set up cron job and start cron daemon
command: |
/bin/bash -c '
echo "Cleanup service starting..." &&
echo "PATH=/usr/local/bin:/usr/bin:/bin:/home/appuser/.local/bin" > /etc/cron.d/cleanup-cron &&
echo "SHELL=/bin/bash" >> /etc/cron.d/cleanup-cron &&
echo "0 * * * * appuser cd /app && /usr/local/bin/python3 scripts/cleanup_temp_files.py --age-hours $${CLEANUP_OUTPUT_AGE_HOURS:-24} --temp-svg-age-hours $${CLEANUP_TEMP_SVG_AGE_HOURS:-1} >> /var/log/cleanup.log 2>&1" >> /etc/cron.d/cleanup-cron &&
echo "" >> /etc/cron.d/cleanup-cron &&
chmod 0644 /etc/cron.d/cleanup-cron &&
echo "Cron file contents:" &&
cat /etc/cron.d/cleanup-cron &&
printenv | grep -E "^CLEANUP_" >> /etc/environment &&
touch /var/log/cleanup.log &&
chown appuser:appuser /var/log/cleanup.log &&
echo "Cron job configured. Cleanup will run every hour at minute 0." &&
echo "Checking for other cron files..." &&
ls -la /etc/cron.d/ &&
echo "Starting cron daemon..." &&
exec cron -f -L 15
'
restart: unless-stopped
depends_on:
- app
healthcheck:
# Disable healthcheck for cleanup service (cron runs in background)
disable: true
# Named volumes for persistent data
volumes:
# ClamAV virus database - persists virus definitions across container restarts
clamav-db:
# PostgreSQL data - persists analytics database across container restarts
postgres-data: