By now many of us have had a chance to learn about the benefits of Docker, but one piece of the puzzle is missing before we move it to production. While Cloud 66 and other solutions exist to manage Docker in production, the pain point I've seen so far actually lies in getting comfortable with running it in development.
Sure, it's easy to put a Dockerfile in your repository and use BuildGrid to build the images. But what happens if the build process fails - do you tweak the Dockerfile and redeploy? I've been there before and I'll tell you, it's far from ideal to do this. What if you want to troubleshoot something inside the container once it comes up? Or make a quick code change?
The list goes on and on, eventually making it clear to me that development work belongs locally. This doesn't preclude building the images that you'll use in production - BuildGrid will still do that. But we want to avoid using it for our development workflows.
In this post, we'll go through how to setup your Docker development environment from scratch on Mac OS X, and outline best practices around doing so.
Install boot2docker
Since you can't run Docker natively in OS X, we'll use boot2docker to setup a virtual machine with Docker in it. This may sound daunting, but it's really straightforward.
Simply visit the boot2docker install page, download the latest pkg
file and install it. You can now run docker
commands in your terminal!
Install Docker Compose
Next we'll want to install Compose (formerly known as Fig), which makes it really easy to spin up multi-container applications from a single file. This is great for development, as you can have your application running alongside your database and cache, all in Docker containers and managed by Compose.
To install it, run the following commands:
curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
Using Compose is a three step process:
- Define your application
Dockerfile
- Define your services in a
docker-compose.yml
file - Run
docker-compose up
to start the entire application
1. Define your application Dockerfile
Your Dockerfile is a textfile that contains all the commands you'd normally execute manually in order to build a Docker image. We're going to use the awesome lets-chat project for illustrative purposes here - pulling it yourself will help you better follow this guide. They use this Dockerfile:
FROM node:0.10-onbuild
MAINTAINER SD Elements
ENV LCB_DATABASE_URI mongodb://db/letschat
EXPOSE 5000
The FROM
directive will pull the library/node image from Docker Hub (tagged 0.10) to be used as a base. The onbuild
directive ensures that certain commands in that image only run when it's being used as a base image. Next, the MAINTAINER
instruction is simply the author of the file, and ENV
sets an environment variable for the container. Finally, EXPOSE
informs Docker that the container should listen on port 5000 at runtime.
2. Define your services
Now that our Dockerfile is ready, we're going to switch over to our Compose setup, which will orchestrate the link between this application and its MongoDB datastore dependency.
Let's create a docker-compose.yml
file that contains the following (they have a fig.yml
file there already, so you can also just rename it):
web:
build: .
links:
- db:db
ports:
- 5000:5000
db:
image: mongo:latest
3. Run Docker Compose
At this point we're ready to see some action. Run docker-compose up
in your terminal, and watch Compose orchestrate your dependencies - if you don't already have MongoDB, this will be fetched, your application image will be built, and everything will be linked.
Once you see the LETS-CHAT
text across your screen, your application is up and running. We just need to know the IP address of our Docker host - run boot2docker ip
in your terminal, and you can now visit ip:5000
in your browser to start chatting!