我有一个简单的 Scala 应用程序将消息生成到 Kafka 中。 Kafka 和 Scala 应用程序都在同一 VM 上的不同容器中运行。
@main def kafkaTest: Unit =
// Kafka producer initialisation
val kafkaProps = new Properties()
kafkaProps.put("bootstrap.servers", "localhost:9092")
kafkaProps.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
kafkaProps.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")
kafkaProps.put("linger.ms", "0")
val producer = new KafkaProducer[String, String](kafkaProps)
producer.send(new ProducerRecord[String, String]("test-topic", "Test message"))
producer.close()
如果我直接在 VM 上(而不是在容器中)构建并运行 Scala 应用程序,代码将按预期工作。但是,如果我在 Docker 容器中运行代码,那么生产者似乎无法连接到 Kafka(没有消息写入 Kafka)。
我也尝试过使用主机网络运行 docker 容器,但仍然面临同样的问题:
docker run <image_name> --network host
因此,我怀疑这是一个 Docker/网络问题,因为如果直接在 VM 上而不是在容器中运行,代码会按预期工作。
用于设置 Kafka 的 Docker compose 文件:
version: '3.8'
services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
hostname: zookeeper
container_name: zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
kafka:
image: confluentinc/cp-kafka:latest
hostname: broker
container_name: broker
depends_on:
- zookeeper
ports:
- "29092:29092"
- "9092:9092"
- "9101:9101"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_JMX_PORT: 9101
KAFKA_JMX_HOSTNAME: localhost
所以我的问题是:如何从一个容器中运行的 Scala 应用程序连接到另一个容器(在同一虚拟机上)中运行的 Kafka?
错误出在用于启动 Scala 容器的命令中。
--network
选项需要出现在图像名称之前:
docker run --network=host <image_image>
代替
docker run <image_name> --network=host