Using Vagrant and Docker Machine Together
Published on 4 Aug 2015 · Filed in Tutorial · 675 words (estimated 4 minutes to read)In this post, I’m going to show you a quick tip I used today to combine the power of Vagrant with that of Docker Machine to quickly and easily create Docker-enabled virtual machines (VMs) on your laptop. This could be useful in a variety of scenarios; I leave it as an exercise for the reader to determine the best way to leverage this functionality in his or her own environment.
In my case, I needed to be able to easily create/destroy/recreate a couple of Docker-enabled VMs for a project on which I’m working. The problem I faced was that the tools I would normally use for such a task—Vagrant and Docker Machine—each had problems when used on their own:
- Vagrant has a Docker provisioner, but I could only get it to install the latest released version of Docker. In my case, I needed to run a test version (specifically, the RC2 build of Docker 1.8.0).
- Docker Machine has various back-end drivers that can create VMs into which Docker is provisioned, but the VMware Fusion driver for Machine only works with Boot2Docker. In my case, I needed to run Ubuntu 14.04 in the VMs.
As it turns out, you can combine these two tools to gain some of the flexibility I needed in my specific circumstances. This allows you to use Vagrant (and the associated provider; VMware Fusion in my case) to handle the VM provisioning, and then use Docker Machine to provision Docker into the Vagrant-managed VMs. Here’s how it works.
-
First, create a Vagrant environment that defines the VM(s) you want created and managed by Vagrant. I won’t cover that here, but you can review my list of Vagrant-tagged articles for more information on how you might accomplish this step.
-
Use
vagrant up
to instantiate the VM(s) you defined in your Vagrant environment. -
Once Vagrant has created and started the VMs, verify that you have SSH connectivity using
vagrant ssh
(orvagrant ssh <VM-name>
if you have more than one VM in the Vagrant environment). -
Provision Docker into the new VM(s) using this command (note that I’ve line-wrapped the command here with backslashes):
docker-machine create -d generic \ --generic-ssh-user vagrant \ --generic-ssh-key ~/.vagrant.d/insecure_private_key \ --generic-ip-address <IP address of VM> \ --engine-install-url "https://test.docker.com" \ <vm-name>
There are a couple of notable things about this command:
- This uses Docker Machine’s generic driver to import an existing VM (the VM created/configured/managed by Vagrant).
- This assumes that you’re allowing Vagrant to continue to use the public insecure SSH key (i.e., that
config.ssh.insert_key
is set to False in yourVagrantfile
). Change this path accordingly if that isn’t the case. - The
--engine-install-url
is what allows you to install a test/pre-release version of Docker. (Want to install an experimental build? Just change the URL provided with this parameter.)
-
To connect your local Docker client to this newly-provisioned Docker Engine, run
eval "$(docker-machine env vm-name)"
and you’re all set.
From here, you can use all the standard Docker commands to pull images, launch containers, etc., using the local Docker client. If you need to access a shell within the VM, you can use either vagrant ssh <vm-name>
or docker-machine ssh <vm-name>
. Both will work just fine.
When you’re finished with the environment, or if you need to rebuild the environment for whatever reason, it’s simple:
- Run
docker-machine rm <vm-name>
to remove the VM from Docker Machine’s list of available Docker Engines. - Run
vagrant destroy <vm-name>
to destroy the VM so that it can be re-provisioned with a clean image.
Because you’re using Vagrant to provision the VMs, you have all the flexibility that Vagrant offers—choosing the OS to go into the VM, running provisioners against the new VM, etc. Because you’re provisioning Docker with Docker Machine, you have the ability to specify release, test, or experimental versions of Docker should be provisioned into the VM.
I hope someone else finds this useful.
UPDATE: I published this update to add some information about using Vagrant and Docker Machine together with Vagrant providers that leverage a forwarded port on the loopback address for connectivity.