name: async-transaction-service x-app: &app build: . environment: &app-env DATABASE_URL: mysql+asyncmy://app:app@mysql:3306/transactions KAFKA_BOOTSTRAP: kafka:9092 REDIS_URL: redis://redis:6379/0 RISK_SERVICE_URL: http://risk:8081 LOG_LEVEL: INFO depends_on: mysql: {condition: service_healthy} kafka: {condition: service_healthy} redis: {condition: service_healthy} services: mysql: image: mysql:8.4 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: transactions MYSQL_USER: app MYSQL_PASSWORD: app ports: ["3306:3306"] healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"] interval: 3s timeout: 5s retries: 30 # Kafka 4.x in KRaft mode: broker and controller in one container, no ZooKeeper. kafka: image: apache/kafka:4.1.0 ports: ["9092:9092"] environment: KAFKA_NODE_ID: 1 KAFKA_PROCESS_ROLES: broker,controller KAFKA_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:29092 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,EXTERNAL://localhost:29092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 KAFKA_NUM_PARTITIONS: 3 KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" CLUSTER_ID: 5L6g3nShT-eMCtK--X86sw healthcheck: test: ["CMD-SHELL", "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"] interval: 5s timeout: 10s retries: 30 redis: image: redis:8-alpine ports: ["6379:6379"] healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 3s timeout: 3s retries: 20 risk: build: . command: uvicorn risk_service.main:app --host 0.0.0.0 --port 8081 environment: RISK_MODE: ok ports: ["8081:8081"] api: <<: *app command: uvicorn app.adapters.inbound.http_api:app --host 0.0.0.0 --port 8000 ports: ["8000:8000"] relay: <<: *app command: python -m app.adapters.inbound.relay ports: ["8010:8000"] consumer: <<: *app command: faststream run app.adapters.inbound.consumer:app --host 0.0.0.0 --port 8000 environment: <<: *app-env MAX_ATTEMPTS: "${MAX_ATTEMPTS:-5}" # A port range rather than a single port, so `make scale N=3` can start # replicas instead of colliding on 8020. ports: ["8020-8029:8000"]