version: '3.8' networks: proxy: external: true turftracker: driver: bridge services: frontend: build: context: ./frontend dockerfile: Dockerfile command: >- sh -lc " if [ ! -d node_modules ] || [ -z \"$(ls -A node_modules 2>/dev/null)\" ]; then echo '[frontend] Installing dependencies...'; npm install --silent; fi; npm start " environment: - REACT_APP_API_URL=https://turftracker.kaspers.us/api volumes: - ./frontend:/app - frontend_node_modules:/app/node_modules depends_on: - backend networks: - proxy - turftracker labels: - "traefik.enable=true" - "traefik.http.routers.turftracker-frontend.rule=Host(`turftracker.kaspers.us`)" - "traefik.http.routers.turftracker-frontend.entrypoints=websecure" - "traefik.http.routers.turftracker-frontend.tls.certresolver=letsencrypt" - "traefik.http.services.turftracker-frontend.loadbalancer.server.port=3000" - "traefik.docker.network=proxy" - "traefik.constraint=proxy-public" restart: unless-stopped backend: build: context: ./backend dockerfile: Dockerfile command: >- sh -lc " if [ ! -d node_modules ] || [ -z \"$(ls -A node_modules 2>/dev/null)\" ]; then echo '[backend] Installing production dependencies...'; npm install --only=production --silent; fi; npm start " environment: - NODE_ENV=development - DB_HOST=db - DB_PORT=5432 - DB_NAME=${DB_NAME:-turftracker} - DB_USER=${DB_USER:-turftracker} - DB_PASSWORD=${DB_PASSWORD:-password123} - JWT_SECRET=${JWT_SECRET:-dev-secret-key-change-in-production-12345} - AUTHENTIK_CLIENT_ID=${AUTHENTIK_CLIENT_ID:-} - AUTHENTIK_CLIENT_SECRET=${AUTHENTIK_CLIENT_SECRET:-} - AUTHENTIK_BASE_URL=${AUTHENTIK_BASE_URL:-} - AUTHENTIK_CALLBACK_URL=${AUTHENTIK_CALLBACK_URL:-https://turftracker.kaspers.us/api/auth/authentik/callback} - WEATHER_API_KEY=${WEATHER_API_KEY:-} - FRONTEND_URL=https://turftracker.kaspers.us volumes: - ./backend:/app - /app/node_modules depends_on: - db networks: - proxy - turftracker labels: - "traefik.enable=true" - "traefik.http.routers.turftracker-backend.rule=Host(`turftracker.kaspers.us`) && PathPrefix(`/api`)" - "traefik.http.routers.turftracker-backend.entrypoints=websecure" - "traefik.http.routers.turftracker-backend.tls.certresolver=letsencrypt" - "traefik.http.services.turftracker-backend.loadbalancer.server.port=5000" - "traefik.docker.network=proxy" restart: unless-stopped db: image: postgres:15-alpine environment: - POSTGRES_USER=${DB_USER:-turftracker} - POSTGRES_PASSWORD=${DB_PASSWORD:-password123} - POSTGRES_DB=${DB_NAME:-turftracker} volumes: - postgres_data:/var/lib/postgresql/data - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql networks: - turftracker restart: unless-stopped # Database should not be exposed to proxy network for security flyway: image: flyway/flyway:9 depends_on: - db environment: - FLYWAY_URL=jdbc:postgresql://db:5432/${DB_NAME:-turftracker} - FLYWAY_USER=${DB_USER:-turftracker} - FLYWAY_PASSWORD=${DB_PASSWORD:-password123} # Uncomment if you need to baseline an existing DB without schema history # - FLYWAY_BASELINE_ON_MIGRATE=true command: -locations=filesystem:/migrations migrate volumes: - ./database/migrations:/migrations:ro networks: - turftracker # Not started automatically; run with: docker compose run --rm flyway migrate volumes: postgres_data: frontend_node_modules: backend_node_modules: