# This compose definition builds Laminar images locally. This is meant to be # run at the last step of local development as a check before pushing changes. name: lmnr services: rabbitmq: image: rabbitmq pull_policy: always environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS} healthcheck: test: rabbitmq-diagnostics -q ping interval: 7s timeout: 5s retries: 3 clickhouse: image: clickhouse/clickhouse-server:26.5 pull_policy: always container_name: clickhouse volumes: - type: volume source: clickhouse-data target: /var/lib/clickhouse/ - type: volume source: clickhouse-logs target: /var/log/clickhouse-server/ - type: bind source: ./clickhouse-profiles-config.xml target: /etc/clickhouse-server/users.d/lmnr.xml - type: bind source: ./clickhouse-server-config.xml target: /etc/clickhouse-server/config.d/lmnr.xml environment: CLICKHOUSE_USER: ${CLICKHOUSE_USER} CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD} ulimits: nofile: soft: 262144 hard: 262144 postgres: image: postgres:16 pull_policy: always volumes: - postgres-data:/var/lib/postgresql/data environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} healthcheck: test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"] interval: 2s timeout: 5s retries: 5 valkey: image: valkey/valkey:9.1 pull_policy: always volumes: - valkey-data:/data healthcheck: test: ["CMD", "valkey-cli", "ping"] interval: 5s timeout: 3s retries: 5 quickwit: image: quickwit/quickwit:v0.9.1 pull_policy: always ports: - "7280:7280" # REST API and UI - "7281:7281" # OTLP / gRPC environment: QW_DATA_DIR: /quickwit/qwdata command: ["run"] volumes: - quickwit-data:/quickwit/qwdata healthcheck: test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/7280 && printf 'GET /health/livez HTTP/1.0\\r\\n\\r\\n' >&3 && grep -q '200 OK' <&3"] interval: 10s timeout: 5s retries: 3 app-server: ports: - "${APP_SERVER_HOST_PORT:-8000}:8000" - "${APP_SERVER_GRPC_HOST_PORT:-8001}:8001" - "${APP_SERVER_RT_HOST_PORT:-8002}:8002" build: context: ./app-server container_name: app-server depends_on: postgres: condition: service_healthy rabbitmq: condition: service_healthy clickhouse: condition: service_started quickwit: condition: service_healthy valkey: condition: service_healthy environment: PORT: 8000 GRPC_PORT: 8001 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} RABBITMQ_URL: amqp://${RABBITMQ_DEFAULT_USER}:${RABBITMQ_DEFAULT_PASS}@rabbitmq:5672/%2f SHARED_SECRET_TOKEN: ${SHARED_SECRET_TOKEN} CLICKHOUSE_URL: http://clickhouse:8123 CLICKHOUSE_USER: ${CLICKHOUSE_USER} CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD} CLICKHOUSE_RO_USER: ${CLICKHOUSE_RO_USER} CLICKHOUSE_RO_PASSWORD: ${CLICKHOUSE_RO_PASSWORD} ENVIRONMENT: FULL AEAD_SECRET_KEY: ${AEAD_SECRET_KEY} QUICKWIT_SEARCH_URL: http://quickwit:7280 QUICKWIT_INGEST_URL: http://quickwit:7281 QUICKWIT_SPANS_INDEX_ID: spans_v2 REDIS_URL: ${REDIS_URL} frontend: build: context: ./frontend container_name: frontend ports: - "${FRONTEND_HOST_PORT:-3000}:3000" depends_on: postgres: condition: service_healthy clickhouse: condition: service_started quickwit: condition: service_healthy valkey: condition: service_healthy environment: PORT: 3000 BACKEND_URL: http://app-server:8000 BACKEND_RT_URL: http://app-server:8002 SHARED_SECRET_TOKEN: ${SHARED_SECRET_TOKEN} DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} ENVIRONMENT: FULL LAMINAR_TELEMETRY_DISABLED: "${LAMINAR_TELEMETRY_DISABLED:-false}" CLICKHOUSE_URL: http://clickhouse:8123 CLICKHOUSE_USER: ${CLICKHOUSE_USER} CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD} CLICKHOUSE_RO_USER: ${CLICKHOUSE_RO_USER} CLICKHOUSE_RO_PASSWORD: ${CLICKHOUSE_RO_PASSWORD} CLICKHOUSE_POSTGRES_HOST: postgres CLICKHOUSE_POSTGRES_PORT: "5432" CLICKHOUSE_POSTGRES_DATABASE: ${POSTGRES_DB} CLICKHOUSE_POSTGRES_USER: ${CLICKHOUSE_POSTGRES_USER:-} CLICKHOUSE_POSTGRES_PASSWORD: ${CLICKHOUSE_POSTGRES_PASSWORD:-} CLICKHOUSE_POSTGRES_SCHEMA: ${POSTGRES_SCHEMA:-public} OPENAI_API_KEY: ${OPENAI_API_KEY} AEAD_SECRET_KEY: ${AEAD_SECRET_KEY} QUICKWIT_SEARCH_URL: http://quickwit:7280 REDIS_URL: ${REDIS_URL} # LLM provider for frontend AI features (chat-with-trace, SQL-with-AI). # openai | gemini | bedrock | azure_chat_completions | azure_responses | # azure_anthropic. openai/gemini use LLM_API_KEY (+ optional LLM_BASE_URL); # bedrock uses AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_REGION; the # azure_* providers share LLM_API_KEY + AZURE_RESOURCE_ID (or AZURE_BASE_URL) # and differ only in which API shape they talk to. LLM_PROVIDER: ${LLM_PROVIDER} LLM_BASE_URL: ${LLM_BASE_URL} LLM_API_KEY: ${LLM_API_KEY} AZURE_RESOURCE_ID: ${AZURE_RESOURCE_ID} AZURE_BASE_URL: ${AZURE_BASE_URL} AZURE_API_VERSION: ${AZURE_API_VERSION} # LLM_MODEL_* overrides (optional — per-provider defaults apply when unset). LLM_MODEL_SMALL: ${LLM_MODEL_SMALL} LLM_MODEL_MEDIUM: ${LLM_MODEL_MEDIUM} LLM_MODEL_LARGE: ${LLM_MODEL_LARGE} AWS_REGION: ${AWS_REGION} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} volumes: clickhouse-data: clickhouse-logs: postgres-data: quickwit-data: valkey-data: