Thursday, July 3, 2014

Nobody puts Baby in a Container

When it comes to Docker, using a Mac in a Linux world comes with some challenges.  There are a number of answers out there.  Which is best depends on how much you want to understand underneath the abstraction Docker provides.  In this blog entry we identify the problem and list a few solutions when it comes to network connectivity and Docker.

And when it comes to baby... we mean redis :)

It can be frustrating when the tooling abstracts you from the details,  yet you are required to understand the context of your environment to know that things are different.   This is the case when using Docker on platforms other than Linux.  In this blog we will simple put redis in a docker container and connect to it from the host OS.

Redis Docker Image on Ubuntu

Lets look at a working environment to establish expectations.  

It was only after working this for some time that I ran across a Redis Server.   Lesson 1:(again) search before you build your own thing :).  On my docker registry there is a kensipe/redis container image which contains redis-server.    You can pull the image with the following command.

sudo docker pull kensipe/redis


The container is start with the following command:

sudo docker run --name redis -p 6379:6379 -d kensipe/redis
# future invocations of the server could be 
sudo docker start redis

With redis installed on the host OS, a simple redis-cli connects to the docker instances of redis and away you go!   Isn't it wonderful?  Automatic port assignment and forwarding from localhost.

Once you go Mac...

The problem is on a Mac (and I assume any platform that needs to use boot2docker as a bridge),  the port forwarding is from the bridge, not from the host OS.  When you run docker run --name redis -p 6379:6379 -d kensipe/redis from the Mac command-line and the docker ps reveals that the port mapping is assigned to 0.0.0.0:6379. However starting up the redis-cli doesn't connect.

Fortunately the boot2docker command provides some help.   boot2docker ip will provide the IP address assigned to the underlying VM.  For me it results in 192.168.59.103.   Lets try redis-cli again.   

redis-cli -h 192.168.59.103

This results in a good connection to the redis server from the host OS.

VBox Network Mapping

If you still want to tie it to localhost, there are a couple of things you can do.  The more involved (not tested, but looks to be a superior way) is to follow the instructions http://ispyker.blogspot.com/2014/04/accessing-docker-container-private.html

Another approach is more simple IMO, but comes with some caveats.  We will inform Virtual Box (VBox) to map the ports for us.  The caveats are that you need to bring VBox down to configure it and when VBox comes up will take on that port (which could collide with local services).  Here is the solution:

VBoxManage modifyvm "boot2docker-vm" --natpf1 "redis,tcp,,6379,,6379"
boot2docker start

If you want to evaluate the configuration use:

VBoxManage showvminfo boot2docker-vm

If you want to delete that mapping to run redis locally, then

VBoxManage modifyvm boot2docker-vm --natpf1 delete tcp-port6379

With the mapping in place, the standard defaults for redis-cli launched from the host will map to the redis in a container.