【发布时间】:2019-05-17 01:55:32
【问题描述】:
我想构建一个模块化系统,其中的模块通过 ZeroMQ 进行通信。为了提高可用性,我想对这些模块中的(一些)进行 Dockerize 化,这样用户就不必设置环境。 但是,我无法让 dockerized 发布者让非 dockerized 订阅者接收其消息。
系统
- Ubuntu 18.04
- Python 3.7
- libzmq 版本 4.2.5
- pyzmq 版本为 17.1.2
- Docker 版本 18.09.0,构建 4d60db4
最小测试用例
zmq_sub.py
# CC0
import zmq
def main():
# ZMQ connection
url = "tcp://127.0.0.1:5550"
ctx = zmq.Context()
socket = ctx.socket(zmq.SUB)
socket.bind(url) # subscriber creates ZeroMQ socket
socket.setsockopt(zmq.SUBSCRIBE, ''.encode('ascii')) # any topic
print("Sub bound to: {}\nWaiting for data...".format(url))
while True:
# wait for publisher data
topic, msg = socket.recv_multipart()
print("On topic {}, received data: {}".format(topic, msg))
if __name__ == "__main__":
main()
zmq_pub.py
# CC0
import zmq
import time
def main():
# ZMQ connection
url = "tcp://127.0.0.1:5550"
ctx = zmq.Context()
socket = ctx.socket(zmq.PUB)
socket.connect(url) # publisher connects to subscriber
print("Pub connected to: {}\nSending data...".format(url))
i = 0
while True:
topic = 'foo'.encode('ascii')
msg = 'test {}'.format(i).encode('ascii')
# publish data
socket.send_multipart([topic, msg]) # 'test'.format(i)
print("On topic {}, send data: {}".format(topic, msg))
time.sleep(.5)
i += 1
if __name__ == "__main__":
main()
当我打开 2 个终端并运行时:
- python zmq_sub.py
- python zmq_pub.py
订阅者正确接收数据 (On topic b'foo', received data: b'test 1')
Dockerfile
我创建了以下Dockerfile:
FROM python:3.7.1-slim
MAINTAINER foo bar <foo@spam.eggs>
RUN apt-get update && \
apt-get install -y --no-install-recommends \
gcc
WORKDIR /app
COPY requirements.txt /app
RUN pip install -r requirements.txt
COPY zmq_pub.py /app/zmq_pub.py
EXPOSE 5550
CMD ["python", "zmq_pub.py"]
然后我使用以下命令成功构建了一个 Dockerized 发布者:sudo docker build . -t foo/bar
尝试
尝试 1
现在我有了带有发布者的 docker 容器,我正试图让我的非 dockerized 订阅者接收数据。我运行以下 2 个命令:
python zmq_sub.pysudo docker run -it foo/bar
我在容器中看到我的发布者正在发布数据,但我的订阅者什么也没收到。
尝试 2
考虑到我必须将 dockerized 发布者的内部端口映射到我机器的端口,我运行以下 2 个命令:
python zmq_sub.pysudo docker run -p 5550:5550 -it foo/bar
但是,我收到以下错误:docker: Error response from daemon: driver failed programming external connectivity on endpoint objective_shaw (09b5226d89a815ce5d29842df775836766471aba90b95f2e593cf5ceae0cf174): Error starting userland proxy: listen tcp 0.0.0.0:5550: bind: address already in use.
在我看来,我的订阅者已经绑定到127.0.0.1:5550,因此当我尝试映射它时 Docker 不能再这样做了。如果我将其更改为-p 5549:5550,Docker 不会报错,但与尝试 1 的情况相同。
问题
如何让我的 dockerized 发布者向我的非 dockerized 订阅者发布数据?
代码
编辑 1: 代码已更新,还提供了有关如何使用 docker-compose 进行自动 IP 推断的示例。
【问题讨论】:
-
查看这个帖子:ZMQ communication between two docker container,希望对你有所帮助。
标签: python-3.x docker docker-compose zeromq pyzmq