services: database: image: postgres:16-alpine container_name: ipsextractor-db environment: POSTGRES_DB: ipsextractor POSTGRES_USER: ipsextractor POSTGRES_PASSWORD: ipsextractor ports: - "5432:5432" volumes: - ipsextractor_db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ipsextractor -d ipsextractor"] interval: 5s timeout: 5s retries: 10 redis: image: redis:7-alpine container_name: ipsextractor-redis command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru --save "" ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 extraction: build: context: ./services/extraction dockerfile: Dockerfile container_name: ipsextractor-extraction depends_on: database: condition: service_healthy redis: condition: service_healthy environment: DATABASE_URL: postgresql+psycopg://ipsextractor:ipsextractor@database:5432/ipsextractor REDIS_URL: redis://redis:6379/0 EXTRACTOR_BASE_URL: https://api.openai.com/v1 EXTRACTOR_API_KEY: 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 EXTRACTOR_MODEL: ${EXTRACTOR_MODEL:-gpt-5.4-mini} NORMALIZER_BASE_URL: https://api.openai.com/v1 NORMALIZER_API_KEY: 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 NORMALIZER_MODEL: gpt-5.4-mini EXTRACTOR_TIMEOUT_S: ${EXTRACTOR_TIMEOUT_S:-120} PDF_DPI: ${PDF_DPI:-150} PDF_THREAD_COUNT: ${PDF_THREAD_COUNT:-4} CONCURRENCY_LIMIT: ${CONCURRENCY_LIMIT:-50} ALLOWED_DOCUMENT_TYPES: ${ALLOWED_DOCUMENT_TYPES:-CC,TI,CE,RC,PA,PPT,PEP,EPT,NUIP} ports: - "8001:8001" volumes: - ${IPS_DOCUMENT_ROOT:-./data}:/data - ips_queue:/tmp/ips_queue # Escala horizontalmente: docker compose up --scale worker=4 worker: build: context: ./services/extraction dockerfile: Dockerfile command: python -m worker.main depends_on: database: condition: service_healthy redis: condition: service_healthy deploy: replicas: ${WORKER_REPLICAS:-2} environment: DATABASE_URL: postgresql+psycopg://ipsextractor:ipsextractor@database:5432/ipsextractor REDIS_URL: redis://redis:6379/0 EXTRACTOR_BASE_URL: https://api.openai.com/v1 EXTRACTOR_API_KEY: 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 EXTRACTOR_MODEL: ${EXTRACTOR_MODEL:-gpt-5.4-mini} NORMALIZER_BASE_URL: https://api.openai.com/v1 NORMALIZER_API_KEY: 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 NORMALIZER_MODEL: gpt-5.4-mini EXTRACTOR_TIMEOUT_S: ${EXTRACTOR_TIMEOUT_S:-120} PDF_DPI: ${PDF_DPI:-150} PDF_THREAD_COUNT: ${PDF_THREAD_COUNT:-4} WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-25} ALLOWED_DOCUMENT_TYPES: ${ALLOWED_DOCUMENT_TYPES:-CC,TI,CE,RC,PA,PPT,PEP,EPT,NUIP} volumes: - ips_queue:/tmp/ips_queue cleaning: build: context: ./services/cleaning dockerfile: Dockerfile container_name: ipsextractor-cleaning depends_on: database: condition: service_healthy environment: DATABASE_URL: postgresql+psycopg://ipsextractor:ipsextractor@database:5432/ipsextractor ports: - "8002:8002" api_gateway: build: context: ./services/api_gateway dockerfile: Dockerfile container_name: ipsextractor-api depends_on: - extraction - cleaning environment: EXTRACTION_URL: http://extraction:8001 CLEANING_URL: http://cleaning:8002 ports: - "8000:8000" volumes: ipsextractor_db: ips_queue: