version: '3.8' services: # PostgreSQL Database db: image: postgres:16-alpine container_name: schoolcompare_db environment: POSTGRES_USER: schoolcompare POSTGRES_PASSWORD: schoolcompare POSTGRES_DB: schoolcompare volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" networks: - schoolcompare-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U schoolcompare"] interval: 10s timeout: 5s retries: 5 start_period: 10s # FastAPI Backend backend: build: context: . dockerfile: Dockerfile container_name: schoolcompare_backend ports: - "8000:80" environment: DATABASE_URL: postgresql://schoolcompare:schoolcompare@db:5432/schoolcompare PYTHONUNBUFFERED: 1 volumes: - ./data:/app/data:ro depends_on: db: condition: service_healthy networks: - schoolcompare-network restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80/api/data-info"] interval: 30s timeout: 10s retries: 3 start_period: 30s # Next.js Frontend nextjs: build: context: ./nextjs-app dockerfile: Dockerfile container_name: schoolcompare_nextjs ports: - "3000:3000" environment: NODE_ENV: production # Next.js can access backend via internal network NEXT_PUBLIC_API_URL: http://localhost:8000/api FASTAPI_URL: http://backend:80/api depends_on: backend: condition: service_healthy networks: - schoolcompare-network restart: unless-stopped healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: schoolcompare-network: driver: bridge volumes: postgres_data: