Взаимодействие с контейнером-док-станцией kafka снаружи докера-хозяина

Я построил контейнер докера kafka и организовал его с помощью docker-compose.

Вызывая docker ps я получаю следующую путпут:

CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS              PORTS                                         NAMES
    5bde6f76246e        hieutrtr/docker-kafka:0.0.1    "/start.sh"            About an hour ago   Up About an hour    7203/tcp, 0.0.0.0:32884->9092/tcp             dockerkafka_kafka_3
    be354f1b8cc0        hieutrtr/docker-ubuntu:devel   "/usr/bin/supervisor   About an hour ago   Up About an hour    22/tcp                                        producer1
    50d3203af90e        hieutrtr/docker-kafka:0.0.1    "/start.sh"            About an hour ago   Up About an hour    7203/tcp, 0.0.0.0:32883->9092/tcp             dockerkafka_kafka_2
    61b285f39615        hieutrtr/docker-kafka:0.0.1    "/start.sh"            2 hours ago         Up 2 hours          7203/tcp, 0.0.0.0:32882->9092/tcp             dockerkafka_kafka_1
    20c9c5ccec05        jplock/zookeeper:3.4.6         "/opt/zookeeper/bin/   2 hours ago         Up 2 hours          2888/tcp, 3888/tcp, 0.0.0.0:32881->2181/tcp   dockerkafka_zookeeper_1

Я могу запустить производителя и потребителя внутри контейнера докера, но он не работает снаружи сети докера.

Например:

Я запускаю производителя kafka на своем локальном хосте, и появляется следующая ошибка:

$ kafka_2.9.1-0.8.2.1: bin/kafka-console-producer.sh --topic test --broker-list $DOCKER_HOST:32884
[2015-08-31 06:55:15,450] WARN Property topic is not valid (kafka.utils.VerifiableProperties)
to
[2015-08-31 06:55:20,214] WARN Failed to send producer request with correlation id 2 to broker 1 with data for partitions [test,0] (kafka.producer.async.DefaultEventHandler)
java.nio.channels.ClosedChannelException
    at kafka.network.BlockingChannel.send(BlockingChannel.scala:100)
    at kafka.producer.SyncProducer.liftedTree1$1(SyncProducer.scala:73)
    at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:72)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(SyncProducer.scala:103)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply(SyncProducer.scala:103)
    at kafka.producer.SyncProducer$$anonfun$send$1$$anonfun$apply$mcV$sp$1.apply(SyncProducer.scala:103)

Это мой пример докера kafka на github, который включает упомянутую проблему.

Итак, кто-нибудь испытывает те же проблемы и может мне чем-нибудь помочь?

Дополнительная информация:

(Просто распакуйте ches/kafka и измените что-нибудь для docker-compose):

Ответ 1

В свойствах сервера Kafka вам нужно установить advertised.host.name и advertised.port в ip/порт вашего запущенного контейнера, а затем он должен работать.

Ответ 2

Вам нужно указать имя хост-машины, где был установлен экземпляр докера. Также вам необходимо сопоставить порты с хост-компьютера докеров (общедоступные) с экземпляром контейнера докера (private).

Ответ 3

TL; DR Вывести порт 9092 на хост и отобразить его в порт контейнера 9092 для доступа к брокерам кафки за пределами контейнера. Подробнее см. документация docker-compose.

Я думаю, проблема в том, что вы не открываете порт 9092 вне контейнера. Согласно вашему докеру ps, ваш порт 9092 контейнер отображается динамически в диапазон портов хоста 32882-32884. Когда вы подключаетесь к брокеру, настроенным таким образом, вы получаете метаданные, содержащие порт 9092 для рекламы. С этим производителем метаданных пытается выполнять другие запросы через порт 9092 и терпит неудачу.

Ответ 4

Для записи другой способ заставить моего локального пользователя kafka общаться с удаленным брокером внутри контейнера Docker заключался в том, чтобы добавить запись в мой /etc/hosts: docker-host-ip-address docker-kafka-container-hostname

В любом случае решение Lundahl отлично справилось со мной и кажется чище. Еще чище было бы установить рекламируемые.listeners= host-ip: порт, поскольку рекламируемые.host.name и advertised.port устарели.

Ответ 5

Вот мои два цента, так как мне было трудно понять это.

Мой $ KAFKA_HOME/config/server.properties содержит следующее:

listener.security.protocol.map=INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT

advertised.listeners=INSIDE://${container_ip}:9092,OUTSIDE://${outside_host_ip}:29092

listeners=INSIDE://:9092,OUTSIDE://:29092

inter.broker.listener.name=INSIDE

Это создает два соединения, одно для использования внутри докера, а другое для использования снаружи. Вы должны выбрать новый порт для последнего, в моем случае 29092, убедитесь, что этот порт открыт и сопоставлен докером.

Я еще не смог найти решение без $ {outside_host_ip} в среде, поэтому я предоставляю ip хост-машины как env var.

Тестовое задание:

  1. Войдите в контейнер Kafka и создайте тему: ./kafka-topics.sh -zookeeper zookeeper:2181 --create --topic dummytopic --partitions 1 --replication-factor 1
  2. Из-за пределов контейнера Kafka выполните: ./kafka-console-producer.sh --broker-list 0.0.0.0:29092 --topic dummytopic и ./kafka-console-producer.sh --broker-list 0.0.0.0:29092 --topic dummytopic сообщение

Я надеюсь, что это помогает другим