Full reference for the Docker Compose deployment, including reverse proxy and TLS.
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 2 GB | 4–8 GB |
| Disk | 10 GB | 50 GB+ (depends on retention) |
| OS | Any Linux with Docker 20.10+ | Ubuntu LTS, Debian stable, RHEL 8+ |
Four services: app, executor, mysql, clickhouse. Data is persisted in named Docker volumes; both databases include healthchecks — the app waits for them before starting.
services: app: image: ghcr.io/mlab-sh/ir.mlab.sh:latest ports: - "${APP_PORT:-8080}:8080" depends_on: mysql: { condition: service_healthy } clickhouse: { condition: service_healthy } env_file: .env environment: - DB_HOST=mysql - CH_HOST=clickhouse - EXECUTOR_URL=http://executor:8090 volumes: - uploads:/app_mlab_sh/uploads - logs:/app_mlab_sh/logs restart: unless-stopped executor: image: ghcr.io/mlab-sh/ir.mlab.sh-executor:latest depends_on: clickhouse: { condition: service_healthy } env_file: .env restart: unless-stopped mysql: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: mlabir MYSQL_USER: ${DB_USERNAME} MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s restart: unless-stopped clickhouse: image: clickhouse/clickhouse-server:latest environment: CLICKHOUSE_USER: ${CH_USERNAME} CLICKHOUSE_PASSWORD: ${CH_PASSWORD} CLICKHOUSE_DB: mlabir volumes: - clickhouse_data:/var/lib/clickhouse healthcheck: test: ["CMD", "clickhouse-client", "--query", "SELECT 1"] interval: 5s restart: unless-stopped volumes: mysql_data: clickhouse_data: uploads: logs:
Don't expose app directly. Put nginx, Caddy or Traefik in front for TLS termination, HTTP/2 and request limits.
ir.example.com {
reverse_proxy localhost:8080
encode gzip
}
server {
listen 443 ssl http2;
server_name ir.example.com;
ssl_certificate /etc/letsencrypt/live/ir.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ir.example.com/privkey.pem;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
TRUSTED_PROXY=127.0.0.1 (or your proxy IP) in .env so the app honors X-Forwarded-* headers for client IP logging.
Both database volumes are mountable. The recommended backup is volume-level snapshots plus a logical dump:
docker exec mysql mysqldump -uroot -p$DB_ROOT_PASSWORD mlabir | gzip > mlabir-$(date +%F).sql.gz docker exec clickhouse clickhouse-client --query="BACKUP DATABASE mlabir TO Disk('backups','mlabir-$(date +%F).zip')"