services: kafka: image: confluentinc/cp-kafka:7.6.0 environment: KAFKA_NODE_ID: 1 KAFKA_PROCESS_ROLES: broker,controller KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 CLUSTER_ID: "MkU3OEVBNTcwNTJENDM2Qg" ports: - "9092:9092" healthcheck: test: ["CMD-SHELL", "kafka-topics --bootstrap-server localhost:9092 --list || exit 1"] interval: 10s timeout: 10s retries: 10 kafka-init: image: confluentinc/cp-kafka:7.6.0 depends_on: kafka: condition: service_healthy entrypoint: ["/bin/sh", "-c"] command: | "kafka-topics --bootstrap-server kafka:9092 --create --if-not-exists --topic ai.recognize.paid --partitions 3 --replication-factor 1 && kafka-topics --bootstrap-server kafka:9092 --create --if-not-exists --topic ai.recognize.free --partitions 1 --replication-factor 1" postgres: image: postgres:16-alpine environment: POSTGRES_DB: food_ai POSTGRES_USER: food_ai POSTGRES_PASSWORD: food_ai_local ports: - "5433:5432" volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U food_ai -d food_ai"] interval: 5s timeout: 5s retries: 10 app: build: context: . dockerfile: Dockerfile ports: - "9090:8080" environment: DATABASE_URL: postgres://food_ai:food_ai_local@postgres:5432/food_ai?sslmode=disable FIREBASE_CREDENTIALS_FILE: /app/firebase-credentials.json JWT_SECRET: local-dev-secret-change-in-prod ALLOWED_ORIGINS: http://localhost:3000,http://localhost:9090 KAFKA_BROKERS: kafka:9092 depends_on: postgres: condition: service_healthy kafka: condition: service_healthy volumes: - ./firebase-credentials.json:/app/firebase-credentials.json:ro volumes: pgdata: