services: server: build: context: . dockerfile: docker/server.Dockerfile ports: - "8484:8484" volumes: - impri-data:/app/data environment: DB_PATH: /app/data/impri.db PORT: "8484" HOST: "0.0.0.0" BASE_URL: "http://localhost:8080" WEBHOOK_SECRET: "${WEBHOOK_SECRET:-change-me-in-production}" # Optional — no-op (no Sentry SDK calls at all) when SENTRY_DSN is unset. SENTRY_DSN: "${SENTRY_DSN:-}" SENTRY_ENVIRONMENT: "${SENTRY_ENVIRONMENT:-self-hosted}" restart: unless-stopped healthcheck: # 127.0.0.1, not localhost: in the alpine container `localhost` resolves to ::1 # (IPv6) first, but the server binds IPv4 (0.0.0.0) only — so a `localhost` # probe gets ECONNREFUSED, the server stays "unhealthy", and the ui service # (depends_on: service_healthy) never starts. Pinning IPv4 fixes the healthcheck. test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8484/healthz"] interval: 10s timeout: 5s retries: 3 ui: build: context: ./ui dockerfile: Dockerfile args: # Optional — baked into the built JS at image-build time (Vite env # var), so this must be set before `docker compose build`, not just # before `up`. No-op (no @sentry/browser import at all) when unset. VITE_SENTRY_DSN: "${VITE_SENTRY_DSN:-}" VITE_SENTRY_ENVIRONMENT: "${VITE_SENTRY_ENVIRONMENT:-self-hosted}" ports: - "8080:8080" depends_on: server: condition: service_healthy restart: unless-stopped volumes: impri-data: