I’ve been told I should check out Docker for over a year. Chris Chang and
Noah Seger at the Tribune were both big proponents. They got excited enough I
always felt like I was missing something since I didn’t get it, but I haven’t
had the time to really dig into it until the last few weeks.
After my initial glance at it, I couldn’t see how it was better/different than
using Vagrant and a virtual machine. Over the last few weeks I’ve started
dipping my toes in the Docker waters and now I’m starting to understand what
the big deal is about.
Docker versus VM
I’ve been a longtime fan of Vagrant as a way to quickly orchestrate virtual
machines. That fits my brain. It’s a server that’s run like any other box,
just not on existing hardware. Docker goes a different route by being more
about applications, regardless of the underlying OS. For example, let’s talk
about my npm-cache.
Using this blog post as a base, I wanted to create an easily
deployable nginx instance that would serve as a cache for npmjs.org. The
normal route for this is to get nginx installed on a server and set it up with
the right configuration. You could also add it to an existing nginx server if
you have one running.
Docker views something like this npm-cache less as the pieces of that
infrastructure (nginx and the server its on) and more as an application unto
itself with an endpoint that you need to hit. Its a subtle shift, but
important in a service-oriented world.
Docker has been described as Git for deployment, and there’s a
reason. Each step of a deployment is a commit unto itself that can be shared
and re-orchestrated into something bigger. For example, to start my
npm-cache, I started by using the official nginx container.
The nginx container can be configured by extending it and providing your own
configuration. I used in the configuration from yammer, created a few empty
directories that are needed for the cache to work, then I was almost ready
to go. The configuration needed to know how to handle rewriting the responses
to point to the caching server.
Parameterizing a Container
This is where things got a little tricky for me as a Docker newbie. nginx
rewrites the responses from npm and replaces
registry.npmjs.org with your
own host information. Starting the container I would know that information,
but inside the running container, where the information was needed, I wouldn’t
know unless I had a way to pass it in.
I managed this by creating a simple script called
runner that checks for two
environment variables to be passed in: the required
PORT and the optional
HOST is optional because I know what it is for
boot2docker (what I use locally).
PORT is required because you have to
tell Docker to bind to a specific port so you can control what nginx uses.
runner script outputs information about whether those values are
available, exiting if
PORT isn’t, modifies the
/etc/nginx.conf file, then
nginx. The whole thing is less than 20 lines of code and could
probably be made shorter.
Deploying with Docker
I got all of this running locally, but then the thought occurred to me that
this shouldn’t be that hard to get running in the cloud. We use
Digital Ocean a lot at Continuum, so I decided to see what support
they have for Docker out-of-the-box. Turns out, you can
launch a server with Docker already configured and ready to run.
With that, deploying is ridiculously easy. I started a small box with Docker
installed, then used
ssh to connect to the box, and ran the following
docker pull tswicegood/npm-cache
docker run -d -e HOST=<my server's IP> -e PORT=$PORT -p $PORT:80 tswicegood/npm-cache
That’s it! Including network IO downloading the npm-cache, I spent less than
five minutes from start to finish to get this deployed on a remote server.
The best part, I can now use that server to deploy other infrastructure too!
Making deployment of a piece of infrastructure this easy is not a simple
problem. I’m sure there are all sorts of edge cases that I haven’t hit yet,
but kudos to the Docker team for making this so easy.
Check out Docker if you haven’t. The Getting Started tutorial is