Using Docker Machine to provision a remote docker host

Like many developers my primary machine is a laptop and when developing applications I typically use Docker containers to provide local instances of databases, caches, message queues, and other supporting services.

When running these services via Docker this can often wreak havoc on my machine and cause it to slow down to a crawl even with lots of ram and CPU power. I began exploring options on how to get the ease and flexibility of Docker but use remote computing resources instead. I found that Docker has a great tool for enabling this type of workflow where the containers run on a different host but you can still access them just like they were on your machine.

Docker Machine

Docker has a built in tool called docker-machine that allows you to provision many different types of remote machines as docker hosts. In order for this to run all you need is a remote system that you have SSH access to. Docker can then provision that remote system and your local docker tools can interface with it instead of your local machine.

This allows you to run all sorts of heavier services on the remote machine instead of your local machine. Let’s take a look at how you might provision a simple docker host on a home server.

Docker Machine drivers

Take a look through the documentation and find what driver is appropriate for you. They provide many cloud drivers for running docker instances remotely. In this case we are going to provision a generic host on a ubuntu server running I have running in my home office.

I went ahead and installed Ubuntu 18.04 LTS and I have a basic root account setup. The first thing we need to do is enable SSH key authentication.

SSH Key Authentication

We are going to start by generating a set of keys to use for authentication with ssh-keygen. I named my keys zdocker since that is the hostname of the server I will be connecting to in my office.

Once these keys are generated you can utilize a tool called ssh-copy-id to automatically transfer the public key information to your server. In my case the command looked something like the following.

ssh-copy-id -i ~/.ssh/${PUBLIC_KEY} ${USERNAME}@${IP_ADDRESS}

You will want to replace the placeholders above with the public key, username, and ip address of your server in the command above. Once transferred you can now log into your server via public key authentication. I then went ahead and disabled password login via SSH since the only way we will allowing logins going forward is with the keys.

nano /etc/ssh/sshd_config
# Turn off PasswordAuthentication by setting the value to no
# and making sure it is not commented out like below
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no

Now that we have SSH key authentication we need to enable password-less sudo privileges for the user that we intent to login with. This is required by the docker-machine installer.

Edit the sudoers file

sudo visudo
# Insert a new entry at the bottom that enables passwordless sudo
${USERNAME} ALL=(ALL) NOPASSWD: ALL

You will want to replace the username with the user that you have created on the machine.

Provision a Docker host

Now that we have SSH public key authentication setup with root access its time to let docker-machine provision our server.

docker-machine create \
	--driver generic \
	--generic-ip-address=$IP_ADDRESS \
	--generic-ssh-user $USERNAME \
	--generic-ssh-key ~/.ssh/$PRIVATE_KEY \
	zdocker

You will want to replace the placeholders above with the ip_address, username, private_key, and machine_name which in my example is zdocker.

Note that the machine_name will be what shows up in your CLI tool when you run docker-machine ls . It is how you will reference this remote docker instance when choosing which docker host to use for running your services.

If the provisioning was a success you will be greeted with some output similar to what is below.

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.1.10:2376"
export DOCKER_CERT_PATH="/path/to/a/cert"
export DOCKER_MACHINE_NAME="zdocker"
# Run this command to configure your shell:
# eval $(docker-machine env zdocker)

Next run the eval command in your current shell to point your docker CLI at the remote host.

eval $(docker-machine env zdocker)

You now have docker pointed at a remote docker host. Within this shell all docker commands will utilize the remote system to do its work and your laptops hardware can breathe a little bit easier!