I am planning to dive into the details on ZMQ patterns, sockets and all other fancy stuff zeromq offers so I need to find the best way to write disposable code which allows me to get the learn-test-understand loop as quick as possible. I find the best language for doing that quick&dirty PoCs (or tests) is python so I have created a docker image with the required zeromq libraries and the Python binding installed. This way I can write code in my local environment without needing to install zeromq-related things and I can run it in a ready-to-use (and also throw away) environment.

Creating a Docker Machine to work with

This guide assumes you have installed docker (I am using v1.9.1) and docker-machine (I am using v0.5.1) running on OS X (El Capitan). Create a virtualbox instance with docker engine running on it. Inside the VM we will run our programs:

    docker-machine create -d virtualbox dm-pyzmq

Then, set up the shell environment variables to point to the just created docker machine:

    eval $(docker-machine env dm-pyzmq)

This way, each docker command will be using the docker engine running on the VM named dm-pyzmq.

Test the environment

As already said, we are going to use an image called zmq-pyzmq. We also need to create a couple of simple python programs that I am going to use for testing the workflow. I am going to use this basic chat program. In order to make things easier, I am going to write them here. So first, create a new folder like this:

    mkdir pyzmq-test
    cd pyzmq-test

Now, let's create a simple program for displaying messages received from a socket.

    cat > display.py

Copy and paste this code into the shell console and press CTRL+D when done.

import zmq

def main(addrs):

    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.setsockopt(zmq.SUBSCRIBE, "")
    for addr in addrs:
        print "Connecting to: ", addr
        socket.connect(addr)

    while True:
        msg = socket.recv_pyobj()
        print "%s: %s" % (msg[1], msg[0])

if __name__ == '__main__':
    import sys
    if len(sys.argv) < 2:
        print "usage: display.py <address> [,<address>...]"
        raise SystemExit
    main(sys.argv[1:])

The other program to be created will prompt you to enter messages.

    cat > prompt.py

Copy and paste this code into the shell console and press CTRL+D when done.

import zmq

def main(addr, who):

    ctx = zmq.Context()
    socket = ctx.socket(zmq.PUB)
    socket.bind(addr)

    while True:
        msg = raw_input("%s> " % who)
        socket.send_pyobj((msg, who))


if __name__ == '__main__':
    import sys
    if len(sys.argv) != 3:
        print "usage: prompt.py <address> <username>"
        raise SystemExit
    main(sys.argv[1], sys.argv[2])

Once done, you should open a new shell session because we will need two programs to be launched. First thing to do will be to create a private network for them to be able to connect. And we will use docker for that too:

    docker network create my_net

This will allow us to use container names for connecting one container to the other.

    eval $(docker-machine env dm-pyzmq)
    docker run -it --name prompt --net my_net -v `pwd`:/project oscarmartin/zmq-pyzmq prompt.py "tcp://*:5000" user1

This will create a prompt for entering messages. Do not do anything right now there but keep it open. On the former shell session, execute this:

    docker run -it --net my_net -v `pwd`:/project oscarmartin/zmq-pyzmq display.py "tcp://prompt:5000"

This will connect to the first prompt docker and will echo what it receives from there, so let's try it. Go back to the session where the prompt was expecting some input and write "Hello World!", like this:

    user1> Hello World!

If you go to the session where display docker is running on, you will hopefully see the message too:

user1: Hello World!

So this is the environment I will use to learn about ZeroMQ.