# Shared stable/experimental deployment definition. # The workflow always supplies a distinct project name and VPN-only host port: # assessor_prod -> 10.0.0.154:4173 # assessor_experimental -> 10.0.0.154:4174 # Compose scopes both named volumes by project, so the environments never share # PostgreSQL or artifacts. PostgreSQL is intentionally not published to the host. name: ${ASSESSOR_STACK:-assessor_prod} services: app: build: context: . dockerfile: Dockerfile restart: unless-stopped environment: ASSESSOR_HOST: 0.0.0.0 ASSESSOR_PORT: "4173" ASSESSOR_ARTIFACT_ROOT: /var/lib/assessor/artifacts ASSESSOR_REPORT_ARCHIVE_DIR: /var/lib/assessor/report-archive ASSESSOR_POSTGRES_HOST: postgres ASSESSOR_POSTGRES_PORT: "5432" ASSESSOR_POSTGRES_DB: ${ASSESSOR_POSTGRES_DB:?set ASSESSOR_POSTGRES_DB} ASSESSOR_POSTGRES_USER: ${ASSESSOR_POSTGRES_USER:?set ASSESSOR_POSTGRES_USER} ASSESSOR_POSTGRES_PASSWORD: ${ASSESSOR_POSTGRES_PASSWORD:?set ASSESSOR_POSTGRES_PASSWORD} ASSESSOR_DATABASE_SSL: disable ports: - "${ASSESSOR_BIND:?set ASSESSOR_BIND}:${ASSESSOR_PUBLISH_PORT:?set ASSESSOR_PUBLISH_PORT}:4173" volumes: - assessor-artifacts:/var/lib/assessor/artifacts - assessor-report-archive:/var/lib/assessor/report-archive depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:4173/api/v1/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 10s timeout: 5s retries: 6 start_period: 40s postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${ASSESSOR_POSTGRES_DB:?set ASSESSOR_POSTGRES_DB} POSTGRES_USER: ${ASSESSOR_POSTGRES_USER:?set ASSESSOR_POSTGRES_USER} POSTGRES_PASSWORD: ${ASSESSOR_POSTGRES_PASSWORD:?set ASSESSOR_POSTGRES_PASSWORD} healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 3s retries: 12 volumes: - assessor-postgres-data:/var/lib/postgresql/data volumes: assessor-artifacts: assessor-report-archive: assessor-postgres-data: