services: app: # Pre-built multi-arch images are published to GHCR by # .github/workflows/docker-publish.yml on every push to main and on # tagged releases. Pin to a specific version in production: # e.g. ghcr.io/mbombeck/healthlog:1.2.0 image: ghcr.io/mbombeck/healthlog:latest # Fallback build context: if the image is not yet in the registry, # or you want to test local changes, run `docker compose up --build`. build: context: . dockerfile: Dockerfile container_name: healthlog-app ports: - "3000:3000" environment: # Plain ${VAR} interpolation only — no ${VAR:?error} validation # syntax. Some hosting platforms (e.g. Coolify) parse compose files # eagerly and store the *fallback error string* as the literal value # when the env var is unset, which then breaks the deployment. # Validation is enforced by docker-entrypoint.sh before the app starts. DATABASE_URL: "postgresql://healthlog:${POSTGRES_PASSWORD}@db:5432/healthlog?schema=public" NODE_ENV: production SESSION_SECRET: "${SESSION_SECRET}" ENCRYPTION_KEY: "${ENCRYPTION_KEY}" API_TOKEN_HMAC_KEY: "${API_TOKEN_HMAC_KEY}" NEXT_PUBLIC_APP_URL: "${NEXT_PUBLIC_APP_URL:-http://localhost:3000}" APP_URL: "${APP_URL:-http://localhost:3000}" depends_on: db: condition: service_healthy restart: unless-stopped db: image: postgres:16-alpine container_name: healthlog-db environment: POSTGRES_USER: healthlog POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" POSTGRES_DB: healthlog volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U healthlog"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped volumes: pgdata: