I'm trying to set up a toy example of Docker networking with ZeroMQ in macOS, where the serverd.py
sends a message to the clientd.py
and the client simply displays it using PUSH/PULL. If I run them outside of the container they work fine, but I'm having trouble getting them to communicate when running within separate containers. It seems like my clientd.py
cannot connect to the container name despite them being within the same bridge network. I tried replacing the hostname with the assigned ip address for serverd_dev_1
, but this doesn't work either.
Here's my setup:
I created a new network with
docker network create -d bridge mynet
. Here is the output fromdocker network inpsect mynet
:{ "Name": "mynet", "Id": "cec7f8037c0ef173d9a9a66065bb46cb6a631fea1c0636876ccfe5a792f92412", "Created": "2017-08-19T09:52:44.8034344Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "5fa8dc2f8059d675dfd3dc4f2e50265be99361cd8a8f2730eb273772c0148742": { "Name": "serverd_dev_1", "EndpointID": "3a62e82b1b34d5c08f2a9f340ff93aebd65c0f3dfde70e354819befe21422d0b", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" }, "ec1e5f8c525ca8297611e02bcd3a64198fda3a07ce8ed82c0c4298609ba0357f": { "Name": "clientd_dev_1", "EndpointID": "a8ce6f178a225cb2d39ac0009e16c39abdd2dae02a65ba5fd073b7900f059bb8", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} }
I created
serverd.py
andclientd.py
like this and put them in separate folders along with their Dockerfiles and docker-compose.yml:
serverd.py:
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.PUSH)
address = "tcp://127.0.0.1:5557"
socket.bind(address)
print("Sending to {}...".format(address))
while True:
message = socket.send_string("Got it!")
print("Sent message")
time.sleep(1)
clientd.py:
import zmq
context = zmq.Context()
socket = context.socket(zmq.PULL)
address = "tcp://serverd_dev_1:5557"
socket.connect(address)
print("Listening to {}...".format(address))
while True:
message = socket.recv_string()
print("Client got message! {}".format(message))
I have two Dockerfiles and docker-compose.yml:
Dockerfile for serverd.py:
FROM python:3.6
RUN mkdir src
ADD serverd.py /src/
RUN pip install pyzmq
WORKDIR /src/
EXPOSE 5557
Dockerfile for clientd.py:
FROM python:3.6
RUN mkdir src
ADD clientd.py /src/
RUN pip install pyzmq
WORKDIR /src/
EXPOSE 5557
docker-compose.yml for serverd.py:
dev:
build: .
command: ["python", "-u", "./serverd.py"]
net: mynet
docker-compose for clientd.py:
dev:
build: .
command: ["python", "-u", "./clientd.py"]
net: mynet
serverd.py
starts up as expected withdocker-compose up
:
Sending to tcp://127.0.0.1:5557...
clientd.py
won't start up like this due to it not finding the hostnametcp://serverd_dev_1:5557
.Attaching to countd_dev_1 dev_1 | Traceback (most recent call last): dev_1 | File "./countd.py", line 6, in <module> dev_1 | socket.connect(address) dev_1 | File "zmq/backend/cython/socket.pyx", line 528, in zmq.backend.cython.socket.Socket.connect (zmq/backend/cython/socket.c:5971) dev_1 | File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/socket.c:10014) dev_1 | zmq.error.ZMQError: Invalid argument
If I replace the URI
tcp://serverd_dev_1:5557
withtcp://172.18.0.2:5557
it does not crash anymore, but it is simply idling without receiving any of the messages from the server. Obviously I'm doing something wrong, but I'm not entirely sure what exactly. I feel like I have been following the Docker documentation as closely as possible, and would very much be grateful if you had any ideas.
.bind()
-side, asaddress = "tcp://172.18.0.2:5557"
not to rely on any DNS-resolution and using it also as the respective.connect()
-target on the client-side?EXPOSE
seems just to mediate port-management between host 0/S resources management and docker-abstraction used for isolation, so the internal ( inside-docker-container ) code ought use the properly setup<transport-class>:\\address:port#
on their own view of the world ( from an insider perspective ). – Pennypennyaliner