services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data ports: - "${PORT_DB:-5432}:5432" healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}" ] interval: 5s timeout: 5s retries: 10 backend: build: ./backend restart: unless-stopped ports: - "${PORT_BACKEND:-5000}:5000" environment: DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} SECRET_KEY: ${SECRET_KEY} JWT_SECRET_KEY: ${JWT_SECRET_KEY:-dev-secret-key-change-in-prod-32chars} FLASK_ENV: development FLASK_APP: app CORS_ORIGINS: http://localhost:${PORT_FRONTEND:-5173} volumes: # Hot-reload: bind-mount app code so Flask reloader picks up changes - ./backend/app:/app/app - ./backend/seeds:/app/seeds - ./backend/migrations:/app/migrations depends_on: db: condition: service_healthy frontend: build: ./frontend restart: unless-stopped ports: - "${PORT_FRONTEND:-5173}:5173" environment: VITE_API_HOST: backend volumes: # Hot-reload: bind-mount source, config and public folders - ./frontend/src:/app/src - ./frontend/public:/app/public - ./frontend/index.html:/app/index.html - ./frontend/vite.config.ts:/app/vite.config.ts - ./frontend/vite.config.js:/app/vite.config.js - ./frontend/tailwind.config.ts:/app/tailwind.config.ts - ./frontend/postcss.config.js:/app/postcss.config.js depends_on: - backend volumes: postgres_data: