# Trouve-KA — stack Docker Compose (dev local et déploiement m2m32) # Author: Simon-Pierre Boucher # Contact: contact@spboucher.ai # # Dimensionné pour m2m32 (32 Go RAM) : OpenSearch 2 Go de heap, Postgres léger, # workers scalables via `docker compose up -d --scale crawler-worker=3`. services: postgres: image: postgres:16-alpine environment: POSTGRES_USER: trouveka POSTGRES_PASSWORD: trouveka POSTGRES_DB: trouveka ports: - "${PG_PORT:-5432}:5432" volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U trouveka"] interval: 5s timeout: 3s retries: 20 redis: image: redis:7-alpine ports: - "${REDIS_PORT:-6379}:6379" volumes: - redisdata:/data command: ["redis-server", "--appendonly", "yes"] healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 20 opensearch: image: opensearchproject/opensearch:2.17.1 environment: discovery.type: single-node plugins.security.disabled: "true" OPENSEARCH_JAVA_OPTS: "-Xms2g -Xmx2g" OPENSEARCH_INITIAL_ADMIN_PASSWORD: "TrouveKA!Local1" bootstrap.memory_lock: "true" ulimits: memlock: soft: -1 hard: -1 ports: - "${SEARCH_PORT:-9200}:9200" volumes: - osdata:/usr/share/opensearch/data healthcheck: test: ["CMD-SHELL", "curl -sf http://localhost:9200/_cluster/health || exit 1"] interval: 10s timeout: 5s retries: 30 api: build: context: . dockerfile: infrastructure/docker/backend.Dockerfile command: ["uvicorn", "trouveka.api.main:app", "--host", "0.0.0.0", "--port", "8080"] environment: &backend_env DATABASE_URL: postgresql://trouveka:trouveka@postgres:5432/trouveka REDIS_URL: redis://redis:6379/0 SEARCH_URL: http://opensearch:9200 ADMIN_TOKEN: ${ADMIN_TOKEN:-change-me-admin-token} PUBLIC_URL: ${PUBLIC_URL:-https://www.trouve-ka.com} MAX_GLOBAL_CONCURRENCY: ${MAX_GLOBAL_CONCURRENCY:-24} DEFAULT_HOST_DELAY: ${DEFAULT_HOST_DELAY:-2.0} MAX_RESPONSE_BYTES: ${MAX_RESPONSE_BYTES:-3000000} ports: - "8080:8080" depends_on: postgres: condition: service_healthy redis: condition: service_healthy opensearch: condition: service_healthy restart: unless-stopped migrate: build: context: . dockerfile: infrastructure/docker/backend.Dockerfile command: ["python", "-c", "import asyncio; from trouveka.database import run_migrations; from trouveka.config import get_settings; print(asyncio.run(run_migrations(get_settings().database_url)))"] environment: *backend_env depends_on: postgres: condition: service_healthy restart: "no" crawler-worker: build: context: . dockerfile: infrastructure/docker/backend.Dockerfile command: ["python", "-m", "trouveka.crawler.worker"] environment: *backend_env depends_on: migrate: condition: service_completed_successfully opensearch: condition: service_healthy redis: condition: service_healthy restart: unless-stopped enrichment-worker: build: context: . dockerfile: infrastructure/docker/backend.Dockerfile command: ["python", "-m", "trouveka.enrichment.worker"] environment: *backend_env depends_on: migrate: condition: service_completed_successfully restart: unless-stopped scheduler: build: context: . dockerfile: infrastructure/docker/backend.Dockerfile command: ["python", "-m", "trouveka.scheduler.loop"] environment: *backend_env depends_on: migrate: condition: service_completed_successfully restart: unless-stopped web: build: context: . dockerfile: infrastructure/docker/web.Dockerfile environment: API_URL: http://api:8080 PORT: "3000" ports: - "3000:3000" depends_on: - api restart: unless-stopped volumes: pgdata: redisdata: osdata: