如何构建Docker Compose环境实现Kafka相关容器互通?
问题根源
你的Producer和Consumer容器里配置的bootstrap-servers=localhost:9092是错误的——容器内的localhost指向容器自身,而非宿主机或Kafka容器。Docker Compose默认会为所有服务创建专属网桥网络,容器之间需通过服务名(如kafka1)互相访问,而非localhost。
同时,你的Kafka配置中已定义INTERNAL://kafka1:19092作为容器内部通信的监听地址,Producer和Consumer必须使用这个地址才能正常连接Kafka。
解决方案
1. 修正Producer/Consumer的Kafka配置
将Producer和Consumer项目中的bootstrap-servers替换为kafka1:19092。以你的Consumer配置为例,修改后的application.properties如下:
spring.kafka.bootstrap-servers=kafka1:19092 spring.kafka.consumer.group-id=groupid spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
注意:原配置中单独写
spring.kafka.producer.bootstrap-servers容易混淆,统一使用spring.kafka.bootstrap-servers即可同时覆盖生产者和消费者的连接配置。
2. 优化Docker Compose配置(可选但更规范)
Docker Compose默认会自动创建网桥网络,所有服务默认加入该网络。如果需要更清晰的网络管理,可显式声明网络,并升级Compose语法版本(原1.0版本过于老旧):
version: '3.8' services: zoo1: image: confluentinc/cp-zookeeper:7.3.2 hostname: zoo1 container_name: zoo1 ports: - "2181:2181" environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_SERVER_ID: 1 ZOOKEEPER_SERVERS: zoo1:2888:3888 networks: - kafka-network kafka1: image: confluentinc/cp-kafka:7.3.2 hostname: kafka1 container_name: kafka1 ports: - "9092:9092" - "29092:29092" - "9999:9999" environment: KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181" KAFKA_BROKER_ID: 1 KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO" KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_JMX_PORT: 9999 KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1} KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true" depends_on: - zoo1 networks: - kafka-network producer: image: producer:1.0 hostname: producer1 container_name: producer ports: - "8080:8080" networks: - kafka-network consumer: image: consumer:1.0 hostname: consumer1 container_name: consumer ports: - "18080:18080" networks: - kafka-network networks: kafka-network: driver: bridge
3. 验证Kafka监听配置
你的Kafka配置中KAFKA_ADVERTISED_LISTENERS和KAFKA_INTER_BROKER_LISTENER_NAME的设置是正确的,INTERNAL://kafka1:19092专门用于容器间通信,无需修改。如果需要从宿主机直接访问Kafka,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092也能正常工作。
测试流程
- 重新构建Producer和Consumer镜像(若修改了应用配置)
- 清理旧容器和数据卷:
docker-compose down -v - 启动所有服务:
docker-compose up -d - 查看Producer容器日志确认无连接错误:
docker logs producer - 调用Producer的消息发送API,检查Consumer是否能正常接收消息
内容的提问来源于stack exchange,提问作者Daniel Ferreira Castro

