I’ve written previously about deploying Hubot on Docker, deploying patched Hubot scripts, and bechmarking mass inserts with a Redis Docker container. In this post, I’ll cover how to link a Hubot Docker container to a Redis Docker container to equip Hubot with persistent memory.
As an overview we’re going to:
- Spin up a Redis Docker container with a host directory mounted as a data volume
- Spin up a linked Hubot Docker container that will use Redis as a persistent brain
For my most recent post on Redis mass inserts, I created a basic Redis Docker image that satisfies all of the requirements to be used as a Hubot Redis brain. We’ll bring this up now:
$ docker run --name redis -v /host/dir:/data -d nhoag/redis 3fc0b9888d5428f01ad13a26d1390904d58b9a34a76ce9965469694307781e3b $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3fc0b9888d54 nhoag/redis:latest "redis-server /etc/r 8 seconds ago Up 7 seconds 6379/tcp redis
In the above
docker run, the Redis container is named as ‘redis’, and a directory from the host is mounted as a volume in the Docker container. By mounting a directory from the host as a volume on the guest, we can now retain Redis backup data through a container failure or reprovision. You can get a sense for this by adding a file on the host, editing from the guest, and viewing the change back on the host:
$ echo "Host" > /host/dir/test.txt $ docker exec -it redis sh -c 'echo "Guest" > /data/test.txt' $ cat /host/dir/test.txt Guest
Next up, we need a suitable Hubot Docker image. I previously assembled a Hubot Docker image that almost meets our requirements. As stated on the Hubot Redis Brain page on NPM:
hubot-redis-brain requires a redis server to work. It uses the
REDIS_URLenvironment variable for determining where to connect to. The default is on localhost, port 6379 (ie the redis default).
The following attributes can be set using the
- key prefix
For example, export
REDIS_URL=redis://email@example.com:16379/prefixwould authenticate with
password, connecting to 192.168.0.1 on port 16379, and store data using the
Let’s spin up the old Hubot image without any modifications to scout out what needs to change. I’m using the same build process outlined in my previous post, A Dockerized and Slack-integrated Hubot, where I’ve defined a base Hubot image into which I’ll sprinkle some additional configuration in order to connect to various services:
$ git clone firstname.lastname@example.org:nhoag/bot-cfg.git && cd bot-cfg # Add credentials to ./Dockerfile $ docker build -t="my-bot" . $ docker run -d -p 45678:8080 --name bot --link redis:redis my-bot $ docker exec -it bot env | grep "^REDIS_PORT" REDIS_PORT=tcp://18.104.22.168:6379 REDIS_PORT_6379_TCP=tcp://22.214.171.124:6379 REDIS_PORT_6379_TCP_ADDR=126.96.36.199 REDIS_PORT_6379_TCP_PORT=6379 REDIS_PORT_6379_TCP_PROTO=tcp
From the above environment variables, there are a lot of options for defining a connection to the Redis container, but the easiest option is to use
REDIS_PORT since it has everything we need and can be used as-is. With one new line added to the bot repo (which gets pulled into the Docker image defined here), we have a Hubot that can automatically talk to Redis on start-up.
Here is the addition to
bin/hubot for reference:
After rebuilding the base Hubot image and
my-bot, we now have a suitable Hubot Docker image to auto-connect to our running Redis container.
Let’s spin up the updated Hubot:
# Don't forget to rebuild the my-bot image from the updated Hubot $ docker run -d -p 45678:8080 --name bot --link redis:redis my-bot
To verify that Hubot is connected, let’s attach to the running Redis container and review with
$ docker exec -it redis redis-cli -h 3fc0b9888d54 3fc0b9888d54:6379> SCAN 0 1) "0" 2) 1) "hubot:storage"