# Local development and single-host deployment. # # cp .env.example .env # then edit # docker compose up --build # # Reaching Prometheus and OpenStack still depends on the CX-Tools containers # being up on the same host - see docs/DEPLOYMENT.md. services: app: build: context: . dockerfile: backend/Dockerfile image: cx-triage:local ports: - "${CX_PORT:-8080}:8080" env_file: [.env] environment: CX_DATABASE_URL: ${CX_DATABASE_URL:-postgresql+psycopg://cx:cx@db:5432/cxtriage} CX_STATIC_DIR: /app/static CX_TOOLS_PATH: /opt/cx-tools CX_RUNPOD_EXPORT_DIR: /seed/runpod volumes: # The engine shells out to `docker exec -osc ...`. Mounting the # host's socket makes those *sibling* containers - the ones CX-Tools # already relies on - reachable from inside this one. Not read-only: # `docker exec` needs to create an exec instance. - /var/run/docker.sock:/var/run/docker.sock # CX-Tools itself, straight off the host. Nothing is written to it. - ${CX_TOOLS_HOST_PATH:-../CX-Tools}:/opt/cx-tools:ro # The RunPod monitor's exports, used only to seed demo data. - ${CX_RUNPOD_EXPORT_HOST_PATH:-../RunPod}:/seed/runpod:ro - cx-data:/data # The mounted socket is owned by root, and the image runs as an unprivileged # user, so the container needs to be in the socket's group to use it. On # Docker Desktop that group is 0; on a Linux host it is the host's `docker` # group - find it with `stat -c %g /var/run/docker.sock`. group_add: - "${CX_DOCKER_GID:-0}" depends_on: db: { condition: service_healthy } restart: unless-stopped db: image: postgres:16-alpine environment: POSTGRES_USER: cx POSTGRES_PASSWORD: cx POSTGRES_DB: cxtriage volumes: - cx-db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U cx -d cxtriage"] interval: 5s timeout: 3s retries: 20 restart: unless-stopped volumes: cx-data: cx-db: