networks: kafka-net: driver: bridge volumes: minio-data: services: # Apache Kafka Broker (KRaft mode - no Zookeeper) kafka-broker-1: image: apache/kafka:3.7.1 hostname: kafka-broker-1 container_name: kafka-broker-1 restart: always networks: - kafka-net ports: - "9092:9092" environment: KAFKA_NODE_ID: 1001 KAFKA_MIN_INSYNC_REPLICAS: 1 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_LISTENERS: PLAINTEXT://kafka-broker-1:9094,EXTERNAL://kafka-broker-1:9092,CONTROLLER://kafka-broker-1:9093 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-broker-1:9094,EXTERNAL://kafka-broker-1:9092 KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,EXTERNAL:PLAINTEXT KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0 KAFKA_PROCESS_ROLES: controller,broker KAFKA_CONTROLLER_QUORUM_VOTERS: 1001@kafka-broker-1:9093 KAFKA_LOG_DIRS: /tmp/kafka-logs AUTO_CREATE_TOPICS_ENABLE: "false" # Topic setup helper (bitnami/kafka images were withdrawn; same image as the broker) kafka-setup: image: apache/kafka:3.7.1 hostname: kafka-setup networks: - kafka-net depends_on: - kafka-broker-1 restart: on-failure entrypoint: ["/bin/bash", "-c"] command: - | until /opt/kafka/bin/kafka-topics.sh --bootstrap-server kafka-broker-1:9092 --list >/dev/null 2>&1; do echo "Waiting for Kafka to be ready..." sleep 2 done for topic in test-topic orders payments; do /opt/kafka/bin/kafka-topics.sh --create --if-not-exists --bootstrap-server kafka-broker-1:9092 \ --partitions 3 --replication-factor 1 --topic "$$topic" done echo "Topics created successfully" # MinIO (S3-compatible storage). minio/minio was deleted from Docker Hub # (Sept 2026) and quay.io/minio no longer allows anonymous pulls. minio: image: cgr.dev/chainguard/minio:latest hostname: minio container_name: minio # The Chainguard image runs as uid 65532; root keeps existing minio-data # volumes (created by the old image as root) writable. user: "0:0" networks: - kafka-net ports: - "9000:9000" - "9001:9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin MC_HOST_local: http://minioadmin:minioadmin@localhost:9000 command: ["server", "/data", "--console-address", ":9001"] healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 2s timeout: 5s retries: 30 volumes: - minio-data:/data # MinIO bucket setup (the image's entrypoint is mc) minio-setup: image: cgr.dev/chainguard/minio-client:latest networks: - kafka-net depends_on: minio: condition: service_healthy restart: on-failure environment: MC_HOST_local: http://minioadmin:minioadmin@minio:9000 command: ["mb", "--ignore-existing", "local/kafka-backups"] # Kafka Backup CLI kafka-backup: build: context: . dockerfile: Dockerfile networks: - kafka-net environment: # Not read by kafka-backup itself; configs can use it as ${KAFKA_BROKERS}. KAFKA_BROKERS: kafka-broker-1:9092 # `--config` runs take the S3 endpoint from the YAML (storage.endpoint: # http://minio:9000, path_style: true, allow_http: true). `--path s3://...` # commands (list, describe, validate, offset-rollback, ...) read these # standard AWS_* variables; without them they go to real AWS. AWS_ENDPOINT_URL: http://minio:9000 AWS_ALLOW_HTTP: "true" AWS_ACCESS_KEY_ID: minioadmin AWS_SECRET_ACCESS_KEY: minioadmin AWS_REGION: us-east-1 RUST_LOG: info depends_on: - kafka-broker-1 - minio volumes: - ./config:/config profiles: - tools