Docker内命令行创建Kafka topic正常,同命令写入Shell脚本执行失败
问题根因
docker compose up -d仅保证容器进入运行状态,不会等待Kafka服务完成初始化。Kafka启动时需要先和ZooKeeper建立连接、完成元数据同步、启动端口监听,整个过程需要几秒到十几秒不等。脚本执行时两个命令无缝衔接,此时Kafka还未完成初始化,就会返回Broker不可用的报错。手动执行命令时,两条命令之间的输入间隔刚好等Kafka完成初始化,所以可以执行成功。
可行解决方案
方案1:脚本内添加服务等待逻辑(最通用,无需修改docker-compose配置)
在脚本中添加端口检测逻辑,等待Kafka服务就绪后再执行创建命令,修改后的init.sh参考如下:
#!/bin/zsh docker compose up -d # 等待Kafka服务就绪,最多等待30秒 MAX_WAIT=30 WAIT_CNT=0 while ! nc -z localhost 29092; do if [ ${WAIT_CNT} -ge ${MAX_WAIT} ]; then echo "Kafka启动超时,topic创建失败" exit 1 fi echo "等待Kafka服务启动中..." sleep 1 WAIT_CNT=$((WAIT_CNT+1)) done # 服务就绪后执行创建命令 docker exec kafka kafka-topics --create --bootstrap-server localhost:29092 --partitions 1 --replication-factor 1 --topic Test
如果宿主机未安装nc工具,也可以替换为容器内部的健康检查命令:
while ! docker exec kafka kafka-broker-api-versions --bootstrap-server localhost:9092 > /dev/null 2>&1; do # 超时逻辑同上 done
方案2:通过docker-compose健康检查控制启动流程(更规范)
在docker-compose.yml的kafka服务配置中添加健康检查规则,配置参考:
kafka: image: confluentinc/cp-kafka:latest container_name: kafka depends_on: - zookeeper ports: - "29092:29092" # 新增健康检查配置 healthcheck: test: ["CMD", "kafka-broker-api-versions", "--bootstrap-server", "localhost:9092"] interval: 2s timeout: 2s retries: 15 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
对应修改init.sh脚本的启动命令,让docker等待所有服务健康检查通过后再返回:
#!/bin/zsh # 替换原有docker compose up -d docker compose up -d --wait docker exec kafka kafka-topics --create --bootstrap-server localhost:29092 --partitions 1 --replication-factor 1 --topic Test
优化建议
因为创建topic的命令是在kafka容器内部执行,不需要走宿主机的端口映射,可将命令中的--bootstrap-server localhost:29092修改为--bootstrap-server kafka:9092,使用容器内部网络访问,链路更稳定。
内容的提问来源于stack exchange,提问作者Nando Machado
相关产品推荐
相关产品推荐

