Files
growqr-backend/docker-compose.yml
2026-05-28 17:43:15 +05:30

139 lines
5.1 KiB
YAML

services:
# Postgres for backend metadata (users, actor registry, billing,
# repo/container mappings). PRD §11.
postgres:
image: postgres:16-alpine
container_name: growqr-postgres
environment:
POSTGRES_USER: ${POSTGRES_USER:-growqr}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-growqr}
POSTGRES_DB: ${POSTGRES_DB:-growqr}
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-growqr}"]
interval: 5s
timeout: 5s
retries: 10
restart: unless-stopped
# ── Central Gitea (one org-wide instance, changes.md §2A) ──
# Every user gets a repo inside the GrowQR organization on this instance.
# Per-user Gitea containers are REMOVED — the backend no longer spawns them.
gitea:
image: gitea/gitea:1.22
container_name: growqr-gitea
environment:
USER_UID: "1000"
USER_GID: "1000"
GITEA__server__ROOT_URL: http://localhost:3001
GITEA__server__SSH_PORT: "2222"
GITEA__security__INSTALL_LOCK: "true"
GITEA__service__DISABLE_REGISTRATION: "true"
ports:
- "3001:3000" # HTTP (Gitea listens on 3000 internally)
- "2222:2222" # SSH
volumes:
- gitea-data:/data
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/v1/version || exit 1"]
interval: 10s
timeout: 10s
retries: 15
restart: unless-stopped
# Self-hosted Rivet engine. The backend's Rivet Kit client connects here.
# The unified user agent runs as a durable Rivet actor (changes.md §5).
rivet-engine:
image: rivetgg/engine:latest
container_name: growqr-rivet
ports:
- "6420:6420" # API
- "6421:6421" # Guard/edge
environment:
RIVET__AUTH__ADMIN_TOKEN: ${RIVET_ADMIN_TOKEN:-dev-admin-token}
volumes:
- rivet-data:/data
restart: unless-stopped
# The HTTP backend (Hono + Rivet Kit client + Docker manager).
# Mounts the host Docker socket so it can spawn per-user OpenCode containers.
backend:
build:
context: .
dockerfile: Dockerfile
container_name: growqr-backend
depends_on:
postgres:
condition: service_healthy
gitea:
condition: service_healthy
rivet-engine:
condition: service_started
ports:
- "4000:4000"
environment:
PORT: 4000
NODE_ENV: ${NODE_ENV:-production}
DATABASE_URL: postgres://${POSTGRES_USER:-growqr}:${POSTGRES_PASSWORD:-growqr}@postgres:5432/${POSTGRES_DB:-growqr}
# Central Gitea (shared org-wide instance)
GITEA_URL: http://gitea:3001
GITEA_ADMIN_USER: ${GITEA_ADMIN_USER:-growqr-admin}
GITEA_ADMIN_PASSWORD: ${GITEA_ADMIN_PASSWORD:-growqr-admin-dev}
GITEA_ADMIN_TOKEN: ${GITEA_ADMIN_TOKEN:-}
GITEA_ORG_NAME: ${GITEA_ORG_NAME:-growqr}
# Version tracking for image rollouts (changes.md §9)
OPENCODE_IMAGE_VERSION: ${OPENCODE_IMAGE_VERSION:-1.0.0}
MIGRATION_VERSION: ${MIGRATION_VERSION:-1}
PROMPT_VERSION: ${PROMPT_VERSION:-1}
# Rivet
RIVET_ENDPOINT: http://rivet-engine:6420
RIVET_CLIENT_ENDPOINT: ${RIVET_CLIENT_ENDPOINT:-http://127.0.0.1:4000/api/rivet}
# Auth
CLERK_SECRET_KEY: ${CLERK_SECRET_KEY}
CLERK_PUBLISHABLE_KEY: ${CLERK_PUBLISHABLE_KEY}
SERVICE_TOKEN: ${SERVICE_TOKEN:-dev-service-token}
A2A_ALLOWED_KEY: ${A2A_ALLOWED_KEY:-dev-a2a-key}
# LLM
OPENCODE_API_KEY: ${OPENCODE_API_KEY}
LLM_PROVIDER: ${LLM_PROVIDER:-opencode}
LLM_BASE_URL: ${LLM_BASE_URL:-https://opencode.ai/zen/v1}
LLM_MODEL: ${LLM_MODEL:-kimi-k2.6}
GROW_AGENT_MODEL: ${GROW_AGENT_MODEL:-kimi-k2.6}
# Per-user OpenCode containers
OPENCODE_IMAGE: ${OPENCODE_IMAGE:-ghcr.io/anomalyco/opencode:latest}
USER_CONTAINER_HOST: ${USER_CONTAINER_HOST:-host.docker.internal}
USER_DATA_ROOT: /data/users
USER_PORT_RANGE_START: 20000
USER_PORT_RANGE_END: 29999
# Microservices
INTERVIEW_SERVICE_URL: ${INTERVIEW_SERVICE_URL:-http://host.docker.internal:8007}
ROLEPLAY_SERVICE_URL: ${ROLEPLAY_SERVICE_URL:-http://host.docker.internal:8008}
QSCORE_SERVICE_URL: ${QSCORE_SERVICE_URL:-http://host.docker.internal:8000}
RESUME_SERVICE_URL: ${RESUME_SERVICE_URL:-http://host.docker.internal:8002}
# Frontend
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN:-http://localhost:3000}
volumes:
# Docker-out-of-Docker: backend uses host Docker to spawn per-user OpenCode containers.
- /var/run/docker.sock:/var/run/docker.sock
# Shared host dir that per-user containers will also bind-mount their
# workspace from (so backend and spawned containers see the same files).
- ./.data/users:/data/users
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:4000/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 6
restart: unless-stopped
# Only per-user OpenCode containers are spawned dynamically now.
# Gitea is a central shared service defined above.
# See src/docker/manager.ts for the per-user OpenCode lifecycle.
volumes:
rivet-data:
postgres-data:
gitea-data: