如何同时启动Zookeeper与Kafka?Docker化Python Kafka应用遇阻
嘿,我一眼就看穿问题出在哪了——你在RUN指令里启动Zookeeper,这可是镜像构建阶段的操作啊!咱们来拆解下问题,再给你一套可行的解决方案:
问题根源
RUN指令的本质:RUN是在构建镜像时执行的,每个RUN都会创建一个临时容器执行命令,执行完就提交成镜像层。而zookeeper-server-start.sh默认是前台运行的,它会一直占用这个临时容器的进程,导致后面的kafka-server-start.sh永远没机会执行,构建过程直接卡在这里。- 构建阶段启动服务无效:就算你侥幸绕开阻塞,构建阶段启动的服务在镜像构建完成后也会终止,容器运行时这些服务根本不会自动启动,你的Python应用照样连不上Kafka。
- 另外你的
CMD还有小错误:用了中文引号,而且应用路径写成了.app.py(应该是/app.py)。
解决方案:用启动脚本协调容器运行时的服务
我们需要把服务启动逻辑放到容器运行阶段(用CMD/ENTRYPOINT),并且写一个脚本协调Zookeeper、Kafka和Python应用的启动顺序。
步骤1:创建启动脚本start.sh
#!/bin/bash # 后台启动Zookeeper(-daemon参数让它后台运行) echo "Starting Zookeeper..." cd /kafka_2.11-2.2.0 && ./bin/zookeeper-server-start.sh -daemon ./config/zookeeper.properties # 等待Zookeeper完全启动(不然Kafka会连不上) sleep 10 # 后台启动Kafka echo "Starting Kafka..." cd /kafka_2.11-2.2.0 && ./bin/kafka-server-start.sh ./config/server.properties & # 等待Kafka启动稳定 sleep 15 # 启动Python应用 echo "Starting Python Kafka app..." python /app.py
步骤2:修改Dockerfile
FROM ubuntu:18.04 # 先添加应用和启动脚本(利用Docker缓存,代码没改就不用重新构建依赖层) ADD app.py / ADD start.sh / RUN chmod +x /start.sh # 给启动脚本加执行权限 # 合并RUN指令,减少镜像层数并清理缓存 RUN apt-get update -y && \ apt-get install -y apt-transport-https wget default-jdk gzip && \ rm -rf /var/lib/apt/lists/* # 清理apt缓存,缩小镜像体积 # 下载解压Kafka并删除压缩包 RUN wget http://mirrors.estointernet.in/apache/kafka/2.2.0/kafka_2.11-2.2.0.tgz && \ tar -xvzf kafka_2.11-2.2.0.tgz && \ rm kafka_2.11-2.2.0.tgz # 容器运行时执行启动脚本 CMD ["/start.sh"]
进阶优化建议(更符合Docker最佳实践)
其实更推荐用多容器编排(比如Docker Compose),把Zookeeper、Kafka和你的Python应用分成三个独立容器,这样每个服务职责单一,维护起来更方便:
编写docker-compose.yml
version: '3' services: zookeeper: image: zookeeper:3.5 ports: - "2181:2181" kafka: image: wurstmeister/kafka:2.12-2.5.0 ports: - "9092:9092" environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 depends_on: - zookeeper app: build: . depends_on: - kafka environment: KAFKA_BOOTSTRAP_SERVERS: kafka:9092
这时你的Python应用只需要连接kafka:9092即可,不用在一个容器里装所有依赖,镜像体积会小很多,也更容易调试。
内容的提问来源于stack exchange,提问作者tyMind
相关产品推荐
相关产品推荐

