services: # ── PostgreSQL ─────────────────────────────────────────────────────────────── postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: ${DB_USER:-taskflow} POSTGRES_PASSWORD: ${DB_PASSWORD:-taskflow_secret} POSTGRES_DB: ${DB_NAME:-taskflow} volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-taskflow} -d ${DB_NAME:-taskflow}"] interval: 5s timeout: 5s retries: 10 # ── Go API ─────────────────────────────────────────────────────────────────── api: build: context: ./backend dockerfile: Dockerfile restart: unless-stopped depends_on: postgres: condition: service_healthy environment: DB_HOST: postgres DB_PORT: ${DB_PORT:-5432} DB_USER: ${DB_USER:-taskflow} DB_PASSWORD: ${DB_PASSWORD:-taskflow_secret} DB_NAME: ${DB_NAME:-taskflow} DB_SSLMODE: ${DB_SSLMODE:-disable} JWT_SECRET: ${JWT_SECRET:-change_me_to_a_long_random_secret} PORT: ${PORT:-8080} ports: - "8080:8080" healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"] interval: 10s timeout: 5s retries: 5 # ── Seed (runs once after API is healthy) ──────────────────────────────────── seed: image: postgres:16-alpine depends_on: api: condition: service_healthy environment: PGPASSWORD: ${DB_PASSWORD:-taskflow_secret} volumes: - ./backend/seed/seed.sql:/seed.sql:ro command: > psql -h postgres -U ${DB_USER:-taskflow} -d ${DB_NAME:-taskflow} -f /seed.sql restart: "no" # ── React Frontend ──────────────────────────────────────────────────────────── frontend: build: context: ./frontend dockerfile: Dockerfile restart: unless-stopped depends_on: api: condition: service_healthy ports: - "3000:80" volumes: postgres_data: