name: lifetrack services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - pgdata:/var/lib/postgresql/data # pg_trgm at initdb time (datamodel-finance ยง2.5). Read-only mount: these # scripts only run on the very first start, when pgdata is still empty. - ./docker/postgres-init:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 api: build: context: . dockerfile: docker/api.Dockerfile image: lifetrack-api:1.0.0 restart: unless-stopped environment: # Every name below is `LIFETRACK_` + a field of app/core/config.py Settings. LIFETRACK_DATABASE_URL: postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} LIFETRACK_JWT_SECRET: ${LIFETRACK_JWT_SECRET} LIFETRACK_TIMEZONE: ${LIFETRACK_TIMEZONE:-Europe/Paris} LIFETRACK_MAX_UPLOAD_BYTES: ${LIFETRACK_MAX_UPLOAD_BYTES:-20971520} ports: # Not needed by the SPA (nginx proxies /api/), but exposing it makes # /api/docs and the ingestion endpoints reachable from other devices. - "${API_PORT:-8000}:8000" depends_on: postgres: condition: service_healthy web: build: context: . dockerfile: docker/web.Dockerfile args: NODE_OPTIONS: ${NODE_OPTIONS:-} image: lifetrack-web:1.0.0 restart: unless-stopped ports: - "${WEB_PORT:-80}:80" depends_on: api: condition: service_healthy volumes: pgdata: