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.
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:
1. Define your application
2. Define your services in a
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
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!