docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# =============================================================================
# FlintTrade Docker Compose — Production Deployment
# =============================================================================
#
# Usage:
# docker compose up -d # start the app services (default profile)
# docker compose up -d --build # rebuild and start the app services
# docker compose --profile monitoring up -d # app + observability stack
# docker compose logs -f flinttrade # follow FlintTrade logs
# docker compose down # stop all services
#
# Profiles:
# default -> flinttrade (backend), terminal (one-shot UI build), nginx (UI origin)
# monitoring -> Uptime Kuma, GlitchTip (+ its Postgres/Redis), VictoriaLogs, Netdata.
# The GlitchTip services need real GLITCHTIP_SECRET_KEY /
# GLITCHTIP_DB_PASSWORD values in .env — the baked-in defaults are
# config-load placeholders only, never production credentials.
#
# Architecture:
# Nginx -> React static files + reverse proxy to backend services. In Docker,
# Nginx is the UI origin: http://localhost:8080 by default (override the host
# ports with FLINTTRADE_HTTP_PORT / FLINTTRADE_HTTPS_PORT).
# FlintTrade (5100) -> Platform backend (strategy engine, screener, AI). The
# image does not contain the built terminal, so port 5100 is API-only in
# Docker — the UI is served by Nginx from the terminal build volume.
# Monitoring stack (profile: monitoring) -> Uptime Kuma, GlitchTip,
# VictoriaLogs, Netdata
#
# All internal services bind to 127.0.0.1 only. Nginx is the sole entry point.
# A .env file is optional: the app services start without one.
#
# Multi-arch builds:
# All base images (python:3.14-slim-trixie, node:22-alpine, nginx:alpine, etc.) support
# linux/amd64 and linux/arm64. To build the FlintTrade image for multiple platforms:
# docker buildx build --platform linux/amd64,linux/arm64 -t flinttrade:latest .
# =============================================================================
services:
# ---------------------------------------------------------------------------
flinttrade:
build:
context: .
dockerfile: Dockerfile
image: flinttrade:latest
platform: linux/amd64
container_name: flinttrade-backend
volumes:
- flinttrade_data:/data/flinttrade
- ${FLINTTRADE_HOME:-~/.flinttrade}:/home/flinttrade/.flinttrade
- flinttrade_strategies:/data/flinttrade/strategies
- flinttrade_logs:/data/flinttrade/logs
ports:
- "127.0.0.1:5100:5100"
# .env is gitignored and absent from a fresh clone; required: false keeps
# `docker compose up` working without it (Compose v2.24+).
env_file:
- path: .env
required: false
environment:
- FLINTTRADE_DEV=0
- FLINTTRADE_BACKEND_PORT=5100
- OPENBLAS_NUM_THREADS=2
- OMP_NUM_THREADS=2
- GUNICORN_WORKERS=1
- GUNICORN_TIMEOUT=120
- LOG_LEVEL=info
restart: unless-stopped
read_only: true
tmpfs:
- /tmp:size=100M
security_opt:
- "no-new-privileges:true"
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:5100/api/v1/ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# Terminal — Build React static files (builder only, no runtime container)
# Nginx serves the built dist/ directory.
#
# This is a pnpm workspace (root pnpm-lock.yaml, no package-lock.json) and the
# terminal imports @flinttrade/design-system via a file: path that lives
# outside the terminal package, so the whole repo must be mounted and built
# through the workspace. The commands mirror the node-core-tests job in
# .github/workflows/test.yml: corepack enable, then a frozen-lockfile install,
# then build the terminal package. Vite writes to the default dist/ inside the
# terminal package, which is the path Nginx mounts via terminal_dist.
# ---------------------------------------------------------------------------
terminal:
image: node:22-alpine
platform: linux/amd64
container_name: flinttrade-terminal-builder
working_dir: /workspace
volumes:
- .:/workspace
- terminal_dist:/workspace/packages/apps/terminal/dist
- terminal_node_modules:/workspace/node_modules
# Corepack is no longer distributed with Node.js from v25.0.0 onwards, so
# 'corepack enable' cannot be relied on once this image moves off the 22
# line. Fall through to a version-matched pnpm and finally to npx with the
# pinned version - the same chain as infra/scripts/setup.sh.
# '$$' escapes Compose's own interpolation so the shell receives '$PNPM'.
command: >
sh -c "if command -v corepack >/dev/null 2>&1; then corepack enable; fi;
if command -v pnpm >/dev/null 2>&1; then PNPM='pnpm';
else PNPM='npx --yes pnpm@10.34.5'; fi;
$$PNPM install --frozen-lockfile &&
$$PNPM --dir packages/apps/terminal run build"
environment:
- NODE_ENV=production
restart: "no"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# Nginx — Reverse proxy and static file server (sole public entry point)
# ---------------------------------------------------------------------------
nginx:
image: nginx:1.30.5-alpine@sha256:0985e772fb9f729e6fa0980da05fca5d9c468e870eed43071545afa9d2e27d94
platform: linux/amd64
container_name: flinttrade-nginx
# High-port defaults so a dev machine with a busy :80/:443 still comes up.
# Production hosts that want the classic ports set FLINTTRADE_HTTP_PORT=80
# and FLINTTRADE_HTTPS_PORT=443 in .env.
ports:
- "${FLINTTRADE_HTTP_PORT:-8080}:80"
- "${FLINTTRADE_HTTPS_PORT:-8443}:443"
volumes:
- ./infra/nginx/flinttrade.conf:/etc/nginx/conf.d/default.conf:ro
- terminal_dist:/var/www/flinttrade/dist:ro
- nginx_logs:/var/log/nginx
# Uncomment when SSL certificates are provisioned:
# - /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
terminal:
condition: service_completed_successfully
flinttrade:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:80/"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# Uptime Kuma — Uptime monitoring dashboard
# Internal only (proxied via Nginx at /monitoring/)
# ---------------------------------------------------------------------------
uptime-kuma:
image: louislam/uptime-kuma:2.5.6@sha256:9912da7d7d9b6ddc0c2d904beb84d24689c1ed9c33b81419eb9008663a92a329
platform: linux/amd64
container_name: flinttrade-uptime-kuma
profiles: ["monitoring"]
ports:
- "127.0.0.1:3001:3001"
volumes:
- uptime_kuma_data:/app/data
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# Glitchtip — Error tracking (Sentry-compatible, MIT licence)
# Internal only (proxied via Nginx at /errors/)
# Requires PostgreSQL for storage + Celery worker for async processing
# ---------------------------------------------------------------------------
glitchtip-redis:
image: redis:8.10.2-alpine@sha256:3811787313eba226a2ef38658c6ccb91cd5e110edc89c37767de373120a0e5a0
platform: linux/amd64
container_name: flinttrade-glitchtip-redis
profiles: ["monitoring"]
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
- flinttrade
glitchtip:
image: glitchtip/glitchtip:6.2.6@sha256:a3d8eb1b36c1e1603d55ab32711ea3dd8115874742a781a57391a62a16e0dff6
platform: linux/amd64
container_name: flinttrade-glitchtip
profiles: ["monitoring"]
ports:
- "127.0.0.1:8000:8000"
depends_on:
glitchtip-db:
condition: service_healthy
# `:-` (not `:?`) — a `:?` here aborts config load for the WHOLE compose
# file, so even `docker compose up flinttrade` failed on an optional
# sidecar. The dev-only defaults exist purely so config loads without a
# .env; set real values before running the monitoring profile.
environment:
DATABASE_URL: "postgres://glitchtip:${GLITCHTIP_DB_PASSWORD:-flinttrade-dev-only-change-me}@glitchtip-db:5432/glitchtip"
SECRET_KEY: "${GLITCHTIP_SECRET_KEY:-flinttrade-dev-only-change-me}"
CELERY_BROKER_URL: "redis://glitchtip-redis:6379/0"
PORT: "8000"
GLITCHTIP_DOMAIN: "http://127.0.0.1:8000"
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
networks:
- flinttrade
glitchtip-worker:
image: glitchtip/glitchtip:6.2.6@sha256:a3d8eb1b36c1e1603d55ab32711ea3dd8115874742a781a57391a62a16e0dff6
platform: linux/amd64
container_name: flinttrade-glitchtip-worker
profiles: ["monitoring"]
command: bin/run-celery-with-beat.sh
depends_on:
glitchtip-db:
condition: service_healthy
glitchtip-redis:
condition: service_started
environment:
DATABASE_URL: "postgres://glitchtip:${GLITCHTIP_DB_PASSWORD:-flinttrade-dev-only-change-me}@glitchtip-db:5432/glitchtip"
SECRET_KEY: "${GLITCHTIP_SECRET_KEY:-flinttrade-dev-only-change-me}"
CELERY_BROKER_URL: "redis://glitchtip-redis:6379/0"
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
networks:
- flinttrade
glitchtip-db:
image: postgres:16.15-alpine@sha256:721873c34ceb9f8d8fc265984940dc982404c105f19ad51be9fdc5970a6080ea
platform: linux/amd64
container_name: flinttrade-glitchtip-db
profiles: ["monitoring"]
volumes:
- glitchtip_pg:/var/lib/postgresql/data
environment:
POSTGRES_USER: glitchtip
POSTGRES_PASSWORD: "${GLITCHTIP_DB_PASSWORD:-flinttrade-dev-only-change-me}"
POSTGRES_DB: glitchtip
healthcheck:
test: ["CMD-SHELL", "pg_isready -U glitchtip"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# VictoriaLogs — Log aggregation and search
# Internal only (proxied via Nginx at /logs/)
# ---------------------------------------------------------------------------
victorialogs:
image: victoriametrics/victoria-logs:v1.53.0@sha256:251121fa882af99b95ba0c230a4a2f412ea602d2698c64a96c58dc9842bb755d
platform: linux/amd64
container_name: flinttrade-victorialogs
profiles: ["monitoring"]
ports:
- "127.0.0.1:9090:9090"
volumes:
- victorialogs_data:/victoria-logs-data
command:
- "-storageDataPath=/victoria-logs-data"
- "-httpListenAddr=:9090"
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
networks:
- flinttrade
# ---------------------------------------------------------------------------
# Netdata — Real-time system performance monitoring
# Internal only (proxied via Nginx at /metrics/)
# ---------------------------------------------------------------------------
netdata:
image: netdata/netdata:v2.12.1@sha256:5cfa05a5fa5686b98e0c70e884f00685fb3c662e9c5d727cf46c96d8e37b7818
platform: linux/amd64
container_name: flinttrade-netdata
profiles: ["monitoring"]
ports:
- "127.0.0.1:19999:19999"
volumes:
- netdata_config:/etc/netdata
- netdata_lib:/var/lib/netdata
- netdata_cache:/var/cache/netdata
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /etc/os-release:/host/etc/os-release:ro
cap_add:
- SYS_PTRACE
security_opt:
- apparmor:unconfined
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
networks:
- flinttrade
# =============================================================================
# Named volumes — persistent data across container restarts
# =============================================================================
volumes:
# Core application
flinttrade_data:
name: flinttrade_platform_data
flinttrade_strategies:
name: flinttrade_strategies
flinttrade_logs:
name: flinttrade_logs
# Terminal build
terminal_dist:
name: flinttrade_terminal_dist
terminal_node_modules:
name: flinttrade_terminal_node_modules
# Nginx
nginx_logs:
name: flinttrade_nginx_logs
# Monitoring
uptime_kuma_data:
name: flinttrade_uptime_kuma_data
glitchtip_pg:
name: flinttrade_glitchtip_pg
victorialogs_data:
name: flinttrade_victorialogs_data
netdata_config:
name: flinttrade_netdata_config
netdata_lib:
name: flinttrade_netdata_lib
netdata_cache:
name: flinttrade_netdata_cache
# =============================================================================
# Internal network — all services communicate over this bridge
# =============================================================================
networks:
flinttrade:
name: flinttrade
driver: bridge