services: frontend: build: context: ./frontend dockerfile: Dockerfile args: BACKEND_INTERNAL_URL: http://backend:8000 NEXT_PUBLIC_INFERIX_API_KEY: ${INFERIX_API_KEY:-} container_name: inferix_frontend env_file: - ./frontend/.env.example - ./.env environment: NEXT_PUBLIC_INFERIX_API_KEY: ${INFERIX_API_KEY:-} ports: - "${FRONTEND_PORT:-3000}:3000" depends_on: backend: condition: service_healthy networks: - platform # ── Dev-only services (opt-in via `--profile dev`) ────────────────────── # Use the dev image for hot reload, typechecks, and lint runs. The image # bakes node_modules at build time; an anonymous volume protects it from # being shadowed by the host bind-mount on /app. frontend-dev: build: context: ./frontend dockerfile: Dockerfile.dev image: inferix-frontend-dev:latest container_name: inferix_frontend_dev profiles: ["dev"] env_file: - ./frontend/.env.example - ./.env environment: BACKEND_INTERNAL_URL: http://backend:8000 NEXT_PUBLIC_INFERIX_API_KEY: ${INFERIX_API_KEY:-} WATCHPACK_POLLING: "true" # reliable file watching on Windows/WSL2 hosts CHOKIDAR_USEPOLLING: "true" ports: - "127.0.0.1:${FRONTEND_DEV_PORT:-3001}:3000" volumes: - ./frontend:/app - frontend_dev_node_modules:/app/node_modules - frontend_dev_next_cache:/app/.next depends_on: backend: condition: service_healthy networks: - platform command: ["npm", "run", "dev"] frontend-typecheck: build: context: ./frontend dockerfile: Dockerfile.dev image: inferix-frontend-dev:latest profiles: ["dev"] volumes: - ./frontend:/app - frontend_dev_node_modules:/app/node_modules networks: - platform command: ["npx", "tsc", "--noEmit", "--pretty", "false"] frontend-lint: build: context: ./frontend dockerfile: Dockerfile.dev image: inferix-frontend-dev:latest profiles: ["dev"] volumes: - ./frontend:/app - frontend_dev_node_modules:/app/node_modules networks: - platform command: ["npm", "run", "lint"] backend: build: context: ./backend dockerfile: Dockerfile container_name: inferix_backend env_file: - ./backend/.env.example - ./.env command: > sh -c "alembic upgrade head && uvicorn app.main:app --host ${BACKEND_HOST:-0.0.0.0} --port ${BACKEND_PORT:-8000}" volumes: - ./backend:/app - ./infra/ansible:/ansible - ./data/logs:/var/log/inferix ports: - "127.0.0.1:${BACKEND_PORT:-8000}:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - platform healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:${BACKEND_PORT:-8000}/health || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 30s worker: build: context: ./backend dockerfile: Dockerfile container_name: inferix_worker env_file: - ./backend/.env.example - ./.env command: celery -A app.workers.celery_app.celery_app worker --loglevel=INFO volumes: - ./backend:/app - ./infra/ansible:/ansible - ./data/logs:/var/log/inferix depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - platform postgres: image: postgres:16-alpine container_name: inferix_postgres environment: POSTGRES_DB: ${POSTGRES_DB:-inferix} POSTGRES_USER: ${POSTGRES_USER:-inferix_user} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data networks: - platform healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-inferix_user} -d ${POSTGRES_DB:-inferix}"] interval: 5s timeout: 5s retries: 10 start_period: 10s redis: image: redis:7-alpine container_name: inferix_redis volumes: - redis_data:/data networks: - platform healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 start_period: 5s # postgres_data and redis_data are named volumes stored in the WSL2 VHD (Linux FS), # so PostgreSQL chmod/chown works correctly on Windows/WSL2 hosts. # They survive "docker compose down" but are wiped by "docker compose down -v". # Logs are bind-mounted to ./data/logs (file writes only, no permission changes needed). volumes: postgres_data: redis_data: frontend_dev_node_modules: frontend_dev_next_cache: networks: platform: driver: bridge