Installation
Full reference for the Docker Compose deployment, including reverse proxy and TLS.
System requirements
| 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+ |
The compose file
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:Reverse proxy & TLS
Don't expose app directly. Put nginx, Caddy or Traefik in front for TLS termination, HTTP/2 and request limits.
Caddy
ir.example.com {
reverse_proxy localhost:8080
encode gzip
}nginx
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. Set TRUSTED_PROXY=127.0.0.1 (or your proxy IP) in .env so the app honors X-Forwarded-* headers for client IP logging.
Backups
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')"