Have you used Docker yet? Docker is awesome! Docker is a tool for managing isolated system environments. I have started using Docker for everything. This is not the first time I’ve written about this delightful tool.
Though the ideas and implementation behind Docker are really cool, the command line syntax is extremely cumbersome. There used to be this great third-party tool to address this problem called fig. But, as of yesterday, it looks like Docker is maintaining
fig and have renamed it to
docker-compose. The impact of this change is minimal on developers - rename
fig.yml files to
docker-compose up instead of
fig up. Some great features have been added that I’ve been sorely missing, including the ability to use environment files and only grabbing the latest tagged images from the hub.
Let’s learn you some
pip install docker-compose (if you’re into that kind of thing) or through a questionable bash script:
You probably want bash completion while you’re at it:
Let’s say I have a simple Go application which only prints the obligatory “Hello, World”:
1 2 3 4 5 6 7
I want to run this with
docker-compose, so I create the following file:
1 2 3 4 5 6
This file specifies using the
golang:1.4 image as the base image. It maps the our code directory to a directory in the
$GOPATH in the container. It then specifies running the command
go run main.go from the working directory of
/go/src/simple-golang-app. So let’s run it:
1 2 3 4 5 6
Composing a Database Connection
Now let’s say I want to connect to a database and find some information. The following example connects to a Mongo database, inserts a record, and spits out all the existing records:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
This application has an external dependency on
mgo, which means I’ll need to have that dependency installed somehow. I’ll make a
Dockerfile to live alongside this example:
1 2 3
Now I’ll construct a yaml file for
docker-compose to consume. This time, we need to
build the main app from our
Dockerfile, add in a second container for the database, add a
link between our application and the database, and specify an
1 2 3 4 5 6 7 8 9 10 11 12 13
mongod has a tendency to spit up a big boilerplate on initialization, I redirect its output to
/dev/null for this example. Let’s see what happens when we compose:
1 2 3 4 5 6 7 8
If you squint, you can see the output next to the
advanced_1 tag. We printed out one item from our database - the one we just added. What if we run it again?
1 2 3 4
This output proves that we’re fetching from the database each time in addition to adding new records. Since the Mongo
Dockerfile we used to build the image creates a
volume, we get to see the data persisted.
To achieve the same goal with the Docker CLI, I would need to do this:
1 2 3 4 5
Keeping that much information at your fingertips all at once absolutely hurts. Making that line reproducible means copy/pasting it into/out of a README somewhere, or running some “single-line script” which only the one guy on the team is allowed to touch.
docker-compose fixes these issues and makes
docker a joy to use.
You can find all of the source code for this blog post on Github: https://github.com/larryprice/docker-compose-example.