services: nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - backend - frontend networks: - hoanet backend: build: context: ./backend dockerfile: Dockerfile.dev # No host port mapping — dev traffic goes through the Docker nginx container. # Production overlay maps 127.0.0.1:3000 for the host reverse proxy. environment: - DATABASE_URL=${DATABASE_URL} - REDIS_URL=${REDIS_URL} - JWT_SECRET=${JWT_SECRET} - NODE_ENV=${NODE_ENV} - AI_API_URL=${AI_API_URL} - AI_API_KEY=${AI_API_KEY} - AI_MODEL=${AI_MODEL} - AI_DEBUG=${AI_DEBUG:-false} - NEW_RELIC_ENABLED=${NEW_RELIC_ENABLED:-false} - NEW_RELIC_LICENSE_KEY=${NEW_RELIC_LICENSE_KEY:-} - NEW_RELIC_APP_NAME=${NEW_RELIC_APP_NAME:-HOALedgerIQ_App} - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY:-} - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET:-} - STRIPE_STARTER_PRICE_ID=${STRIPE_STARTER_PRICE_ID:-} - STRIPE_PROFESSIONAL_PRICE_ID=${STRIPE_PROFESSIONAL_PRICE_ID:-} - STRIPE_ENTERPRISE_PRICE_ID=${STRIPE_ENTERPRISE_PRICE_ID:-} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-} - GOOGLE_CALLBACK_URL=${GOOGLE_CALLBACK_URL:-http://localhost/api/auth/google/callback} - AZURE_CLIENT_ID=${AZURE_CLIENT_ID:-} - AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET:-} - AZURE_TENANT_ID=${AZURE_TENANT_ID:-} - AZURE_CALLBACK_URL=${AZURE_CALLBACK_URL:-http://localhost/api/auth/azure/callback} - WEBAUTHN_RP_ID=${WEBAUTHN_RP_ID:-localhost} - WEBAUTHN_RP_ORIGIN=${WEBAUTHN_RP_ORIGIN:-http://localhost} - INVITE_TOKEN_SECRET=${INVITE_TOKEN_SECRET:-dev-invite-secret} - APP_URL=${APP_URL:-http://localhost} - RESEND_API_KEY=${RESEND_API_KEY:-} - RESEND_FROM_ADDRESS=${RESEND_FROM_ADDRESS:-noreply@hoaledgeriq.com} - RESEND_REPLY_TO=${RESEND_REPLY_TO:-} volumes: - ./backend/src:/app/src - ./backend/nest-cli.json:/app/nest-cli.json - ./backend/tsconfig.json:/app/tsconfig.json - ./backend/tsconfig.build.json:/app/tsconfig.build.json depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - hoanet frontend: build: context: ./frontend dockerfile: Dockerfile.dev # No host port mapping — dev traffic goes through the Docker nginx container. # Production overlay maps 127.0.0.1:3001 for the host reverse proxy. environment: - NODE_ENV=${NODE_ENV} volumes: - ./frontend/src:/app/src - ./frontend/index.html:/app/index.html - ./frontend/vite.config.ts:/app/vite.config.ts depends_on: - backend networks: - hoanet postgres: image: postgres:15-alpine environment: - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - POSTGRES_DB=${POSTGRES_DB} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./db/init:/docker-entrypoint-initdb.d healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 5 networks: - hoanet redis: image: redis:7-alpine command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 5 networks: - hoanet volumes: postgres_data: redis_data: networks: hoanet: driver: bridge