Use Docker-machine to Create Docker Servers

Tue Sep 20, 2016 - 1000 Words

Continuing our series looking into Docker, we’re going to bust open the docker toolbox and look at docker-machine.

Goal for this Tutorial:

  • Create a local Docker host using docker-machine.
  • Look at the difference between docker-machine and Docker for Mac/Windows.

Up to this point we’ve used Docker for Mac (or Windows) exclusively as our Docker server, but you’re more than likely going to run Docker on a Linux machine when not in development. The docker-toolbox has a tool to make it easy to spin up Docker hosts in a variety of linux environments, docker-machine. We’re going to use docker-machine in combination with VirtualBox to manage a Docker host VM locally. Docker for Mac and Windows are graphical applications for working your local Docker host and depending on the platform utilizes different technologies under the hood. Docker for Mac utilizes HyperKit to manage a Linux virtual machine for you, and Docker for Windows utilizes Microsoft Hyper-V. VirtualBox is a cross-platform solution for running virtual machines, and was the primary way of running docker on Mac or Windows before the GUIs were released. There are also performance differences that you might run into using the various technologies.

Creating a Docker Host with Docker-machine

Once you’ve installed VirtualBox to your system you can head to your command line to create your first VM manually.

$ docker-machine create --driver=virtualbox test

This will create a light-weight, Linux VM running a distro called Boot2Docker. You’ll notice that the output says to run docker-machine env test to learn how to connect to the machine, so let’s do that now.

$ docker-machine env test
export DOCKER_HOST="tcp://"
export DOCKER_CERT_PATH="/Users/explorer/.docker/machine/machines/test"
# Run this command to configure your shell:
# eval $(docker-machine env test)

Your values will be different, but it should look similar.

All that we need to do to connect to our new Docker host is set some environment variables. This works because Docker uses a clint-server architecture and our docker command line tool is the client. We configure the client so that it knows which server to talk to using these four environment variables. This makes it easy for us to access multiple Docker hosts from the same machine by changing some of these values. We’ll run the command that it suggests to configure our docker client.

$ eval $(docker-machine env test)

If we run Docker commands now we should get results because it actually has a docker host to connect to. Let’s try this out by listing our our images.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

We didn’t receive any images because we’ve never run a docker pull when connected to our new VM. Since images are stored on the docker host, we’ll have our images again when we connect back up to the Docker for Mac or Windows VM.

Starting, Stopping, and Removing a Docker Host

Now that we have our VM and we’re connected to it, we’re back to where we were before in terms of using Docker. Rather than go through more docker commands, we’re going to look into what else we can do with docker-machine.

The most basic thing that we’ll do with docker-machine is look at the status of the machines that we’re managing.

$ docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
one    -        virtualbox   Stopped                                       Unknown
test   *        virtualbox   Running   tcp://           v1.12.1

We now see the list of machines and some basic information about them.

The state is helpful for seeing if the machine is currently running, and active will let us know which machine our docker command line tool is configured to connect to.

We can start and stop the machines easily to avoid using too many resources on our own machine using similar commands and the name of the machine that we want to work with.

$ docker-machine stop test
Stopping "test"...
Machine "test" was stopped.

Now if we look at the listing they should both have a state of “stopped”. Starting test back up takes a similar command.

$ docker-machine start test
Starting "test"...
(test) Check network to re-create if needed...
(test) Waiting for an IP...
Machine "test" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

And we’re back to where we were originally.

The last thing we’re going to look at is how to remove a machine if we no longer need it. Removing them will be particularly useful in this case so that we’re not wasting hard drive space on our computers, but will be essential later on so we don’t pay for server that we no longer need.

$ docker-machine rm test
About to remove test
Are you sure? (y/n): y
Successfully removed test


Today we learned how to create Docker hosts, specifically local VMs using docker-machine. After we created our VM we then went through some of the life-cycle operations that we can perform on the machine. These operations will be important as we start moving into using Docker on machines other than our development machines. I wanted to make sure that we have a good grasp on how Docker hosts work before we get into deployments with Docker.

In the next tutorial we’re going to use docker-machine to create a server on Digital Ocean, and deploy a Ruby on Rails application to it for the public to access.