Docker/Kafka连接两个不同的容器

Tha*_*nos 2 apache-kafka docker docker-compose

我正在使用wurstmeister 的 docker-kafka项目在容器中运行 kafka/zookeeper。我使用 localhost 作为变量来构建容器KAFKA_ADVERTISED_HOST_NAME: localhost

我编写了一个 Java 应用程序,它使用 flink 连接并使用这个 Kafka 容器的主题之一。如果我导出一个可运行的 jar 并从我的机器上运行它,它绝对可以正常工作。当我创建以下图像以从另一个 docker 容器运行 jar 时,我收到一个异常(执行后大约 30 秒),Exception in thread "main" org.apache.flink.runtime.client.JobExecutionException: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata我认为这与我的 Java 程序无法与另一个容器中运行的 Kafka 服务器通信有关。

这是我的 Java 应用程序的 dockerfile:

# Dockerfile

FROM anapsix/alpine-java

MAINTAINER myself myself

COPY myApp.jar /home/myApp.jar

CMD ["java","-jar","/home/myApp.jar"]
Run Code Online (Sandbox Code Playgroud)

这是 wurstmeister 的 docker kafka 的 docker-compose.yml:

version: "3.5"

networks:
  myNetwork:
    name: myNetwork
    driver: bridge

services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
    networks:
      - myNetwork
  kafka:
    build: .
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: localhost
      KAFKA_ADVERTISED_PORT: "9092"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
      ALLOW_PLAINTEXT_LISTENER: "yes"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - myNetwork
  auth_analytics:
      build: 
        context: .
        dockerfile: auth_dockerfile
      depends_on:
        - kafka
      networks:
        - myNetwork
Run Code Online (Sandbox Code Playgroud)

我已经尝试过以上的多个版本。最初我没有设置任何网络,我认为这可能是问题所在,但是,上面创建的网络没有任何区别。我尝试使用“localhost:9092”作为我的 Java 应用程序中的引导服务器,并尝试使用“myNetwork:9092”作为我在线阅读的内容。

我还阅读了wurstmeister 的有关连接的常见问题解答,但我没有发现我的设置有问题。

我还尝试在不使用 docker-compose 的情况下运行我的 Java 应用程序映像(我运行 docker-compose 来启动 Zookeeper/kafka,然后我在我的 Java 应用程序的映像上进行了 docker 构建、docker 运行。这没有什么区别.)

我被困住了。我究竟做错了什么?

Rob*_*att 5

您需要正确设置KAFKA_ADVERTISED_LISTENERS。目前,这localhost意味着任何连接的客户端都会被代理告知该代理位于localhost\xe2\x80\x94 上,并且当客户端尝试连接到该代理时,它将失败(除非 Kafka 代理实际上在 上可用localhost,这它不会位于仅运行您的应用程序的 Docker 容器上)。

\n\n

解决方案是定义侦听器,以便可以从需要它的任何代理和客户端位置对它们进行寻址。我首选的方法是这样的,一种用于容器内通信,另一种用于从主机进行通信:

\n\n
  KAFKA_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092\n  KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT\n  KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT\n  KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092\n
Run Code Online (Sandbox Code Playgroud)\n\n

Docker 网络上的客户端用于kafka:29092连接;主机上的客户端连接到 localhost:9092(并确保通过 Docker 将 9092 暴露给主机)。

\n\n

要了解更多信息,请参阅https://rmoff.net/2018/08/02/kafka-listeners-explained/

\n\n

顺便说一句,我强烈建议以正确的方式解决这个问题;在我看来,覆盖该/etc/hosts文件是一种无法解决实际问题的黑客行为。

\n