version: "3.9" services: crowdlending-backend: build: context: ./backend dockerfile: Dockerfile container_name: crowdlending-backend restart: unless-stopped env_file: - .env environment: NODE_ENV: production PORT: 4000 DB_PATH: /app/data/crowdlending.db UPLOAD_DIR: /app/uploads DATA_DIR: /app/data volumes: - ../../volumes/crowdlending/data:/app/data - ../../volumes/crowdlending/uploads:/app/uploads healthcheck: test: ["CMD", "node", "-e", "fetch('http://localhost:4000/api/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"] interval: 30s timeout: 5s retries: 3 start_period: 10s networks: - internal crowdlending-frontend: build: context: ./frontend dockerfile: Dockerfile args: VITE_API_URL: /api container_name: crowdlending-frontend restart: unless-stopped depends_on: crowdlending-backend: condition: service_healthy labels: - "traefik.enable=true" - "traefik.http.routers.crowdlending.rule=Host(`crowdlending.croguennec.net`)" - "traefik.http.routers.crowdlending.entrypoints=websecure" - "traefik.http.routers.crowdlending.tls.certresolver=le" - "traefik.http.routers.crowdlending.middlewares=ipwhitelist-all@file" - "traefik.http.services.crowdlending.loadbalancer.server.port=80" networks: - internal - backend # réseau Traefik # Serveur MCP (Phase 5) — même image/code que le serveur utilisé en # développement local (mcp-server/server.js, npm run dev), déployé ici # accessible publiquement sur un sous-domaine dédié, SANS le middleware # ipwhitelist-all : contrairement au reste de l'app, ce service est # volontairement ouvert à des utilisateurs distants qui ne peuvent pas # faire tourner le serveur en local. La clé API (en-tête X-API-Key, propre # à chaque utilisateur) est donc la SEULE barrière d'accès. crowdlending-mcp: build: context: ./mcp-server dockerfile: Dockerfile container_name: crowdlending-mcp restart: unless-stopped environment: NODE_ENV: production PORT: 4100 CROWDLENDING_API_URL: http://crowdlending-backend:4000/api/v1 MCP_ALLOWED_HOSTS: mcp.crowdlending.croguennec.net,localhost MCP_LABEL: prod # Explicitement désactivé : ce serveur sert des utilisateurs distants # non maîtrisés, l'outil de lecture d'URL arbitraire (SSRF) reste # réservé au développement local. Ne pas passer à true ici. MCP_ENABLE_FETCH_URL: "false" depends_on: crowdlending-backend: condition: service_healthy labels: - "traefik.enable=true" - "traefik.http.routers.crowdlending-mcp.rule=Host(`mcp.crowdlending.croguennec.net`)" - "traefik.http.routers.crowdlending-mcp.entrypoints=websecure" - "traefik.http.routers.crowdlending-mcp.tls.certresolver=le" - "traefik.http.services.crowdlending-mcp.loadbalancer.server.port=4100" networks: - internal - backend # réseau Traefik networks: internal: # communication interne backend <-> frontend driver: bridge backend: # réseau partagé avec Traefik external: true