Docker Workflow from Development to Production

docker run ubuntu /bin/echo "Hello World!"
Hello World!

Simple enough, but the power of this command is amazing and allows us to do incredible things.

This is what goes on behind the scenes when that command is run:

  • Docker searches your local machine's cache to see if you already have the 'ubuntu' image downloaded. If so, it uses it. If not:
  • The DockerHub Registry is searched for the 'ubuntu' image and it is downloaded.
  • A virtual machine is 'spun up' using that image. This happens almost instantly.
  • The VM runs the /bin/echo command with the argument "Hello World!"
  • Then the VM shuts down and has no memory of what it just did. It is back to its base state, ready to be run again.

What problem does Docker solve?

A common problem with deploying web apps is that the production environment doesn't exactly match the development environment and there ends up being a slew of minor annoyances in the form of bugs and config/environment issues.

If you don't deploy very often, you forget what to do in between deployments. And if you do deploy often, you perform the same time-consuming repetitive tasks over and over again.

Docker is like having GitHub for virtual machines.

It allows you to start with a base image of a barebones linux distribution and install just the services and software you need and let you commit a snapshot of that virtual machine every step along the way.

It is super simple to use. Once you get the pre-requisite software installed, a new image can be booted up by simply running the command:

docker run -it ubuntu /bin/bash

That command uses the -i option to make the session interactive and the -t option to give you a pseudo-terminal in the container running the bash shell. For a full list of run options, visit the Docker run reference.

Here is a quick overview of some of the things I found most exciting.

  • The Docker "containers" (basically virtual machines) are able to boot up and shut down in just a few seconds.
  • You can link containers together so they can talk to each other. It is very easy to have separate containers for your web server (e.g. nginx), web app (e.g. node/express), and database (e.g. mongo/mysql)
  • Base images are provided through the DockerHub Registry. Images are automatically downloaded if you use docker run [flags] [image] if you don't already have the image.
  • Files and folders can be mapped from your local machine into the docker container. Those files and folders will be kept in sync between your local machine and the container.

Putting all of this together means we have the ability for everyone on our development team to be developing/testing the app on the exact same environment - the same environment that we are deploying too.

"Dockerized" apps are isolated, portable, and can be run on Windows, Mac, or Linux.

How to install Docker (Mac)

To get started with Docker, make sure you have homebrew installed.

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

Then install brew-cask and virtualbox.

brew update
brew tap phinze/homebrew-cask
brew install brew-cask
brew cask install virtualbox

Install boot2docker and add a DOCKER_HOST environment variable so that you can send docker commands from your host terminal, through the boot2docker virtual machine, to the docker container.

brew install boot2docker
boot2docker init
boot2docker up
export DOCKER_HOST=tcp://localhost:4243

Then install docker itself.

brew install docker
docker version

In the future, if you want to use a docker-compose.yml file to create multiple containers and automatically map volumes, ports, and link containers together, install docker-compose with the command:

sudo pip install -U docker-compose

This concludes part 1 of what will be a multi-part blog post. In the next posts, we will dig deeper into the docker 'run' command options, how to link containers together, and then we will set up a complete development to production environment and workflow for an example MEAN stack web app.

Check out Part 2 of Docker Workflow from Development to Production