Vagrant (again)

As we have already discovered earlier in this chapter, Vagrant can be used as a virtual machine manager. We have already used it to bring up a local Ubuntu 14.04 instance using VirtualBox on our local machine; however, if we wanted to, we could have done this using VMware Fusion, Amazon Web Services, DigitalOcean, or even OpenStack.

Like Puppet and Ansible, when Docker was first released, there were a lot of articles published around Vagrant versus Docker. In fact, when the question was asked on Stack Overflow, the authors of both Vagrant and Docker weighed in on the question. You can read the full discussion at http://stackoverflow.com/questions/16647069/should-i-use-vagrant-or-docker-for-creating-an-isolated-environment

So, in what ways can Vagrant support Docker? There are two main ones we are going to be looking at. The first is the provisioner.

Provisioning using Vagrant

When we worked out way through Puppet, we used Vagrant to launch Ubuntu 14.04 locally using VirtualBox; as part of that, we used the Shell provisioner to install Puppet and deploy the Docker Puppet module. Vagrant has the following provisioners available:

  • File: This copies files in place onto the Vagrant host
  • Shell: This compiles/copies bash scripts to the host and executes them
  • Ansible: This runs an Ansible playbook either on or against the host
  • Chef and Puppet: There are around dozen different ways you can use Chef or Puppet to provision your Vagrant host
  • Docker: This is what we will be using to provision our containers on the Vagrant host

The Vagrantfile looks really close to the one we used to deploy our Puppet WordPress example:

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "ubuntu/trusty64"
  config.vm.network "private_network", ip: "192.168.33.10"
  HOSTNAME = 'docker'
  DOMAIN   = 'media-glass.es'
  Vagrant.require_version '>= 1.7.0'
  config.ssh.insert_key = false
  config.vm.host_name = HOSTNAME + '.' + DOMAIN

  config.vm.provider "VirtualBox" do |v|
    v.memory = 2024
    v.cpus = 2
  end

  config.vm.provider "vmware_fusion" do |v|
    v.vmx["memsize"] = "2024"
    v.vmx["numvcpus"] = "2"
  end

  config.vm.provision "docker" do |d|
    d.run "mysql",
      image: "mysql",
      args: "-e 'MYSQL_ROOT_PASSWORD=password'"
    d.run "wordpress",
      image: "wordpress",
      args: "-p 80:80 --link mysql:mysql -e WORDPRESS_DB_PASSWORD=password"
  end

end

As you can see, this will download (if you don't have it already) and launch an Ubuntu 14.04 server and then provision two containers, one WordPress and one MySQL.

To launch the host, run the following command:

vagrant up --provider VirtualBox

You should see something similar to the following terminal output:

Provisioning using Vagrant

You can also run the following command to open your browser and get to your WordPress installation screen (remember: we have launched the Vagrant host with a fixed local IP address, which means the following URL should resolve to your local installation):

open http://docker.media-glass.es/

You may have already noticed one thing that happened when we launched the Vagrant host: we didn't have to provide Vagrant any commands to install Docker; it took care of that for us.

Also, we had to launch our MySQL container before we launched our WordPress one. This is because we have linked our WordPress container to the MySQL one. If we tried to launch the WordPress container first, we would have received an error telling us that we are trying to reach a link that does not exist.

As you can see from the following terminal output, you can connect to your Vagrant host using the vagrant ssh command:

Provisioning using Vagrant

The other thing you may notice is that the Docker version installed isn't the most up-to-date one; this is because Vagrant installs the version that is available in the operating system's default repository rather than the latest version provided by Docker in their repository.

The Vagrant Docker provider

As I mentioned, there are two ways in which you can use Docker with Vagrant: the one we just looked at is a provisioner, and the second way is to use a provider.

So, what's a provider? We have already used a provider twice in this chapter when we launched our Docker hosts. A provider is a virtual machine process, manager, or API that Vagrant can make a connection to and then launch a virtual machine from.

Vagrant has the following providers built in:

  • VirtualBox
  • Docker
  • Hyper-V

There is also a commercial plugin provided by the authors, which adds the following provider:

  • VMware Fusion and Workstation

Finally, Vagrant supports custom providers, such as ones for Amazon Web Services, libvirt, and even LXC, for example. A full list of custom providers and other Vagrant plugins can be found at http://vagrant-lists.github.io/.

Obviously, if you are using OS X, then you won't be able to use the Docker provider natively; however, Vagrant takes care of this you. Let's look at launching an NGINX container using the Docker provider rather than a provisioner.

The Vagrantfile looks a little different to the ones we have been using:

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "boot2docker", autostart: false do |dockerhost|
    dockerhost.vm.box = "russmckendrick/boot2docker"
    dockerhost.nfs.functional = false
    dockerhost.vm.network :forwarded_port, guest: 80, host: 9999
    dockerhost.ssh.shell = "sh"
    dockerhost.ssh.username = "docker"
    dockerhost.ssh.password = "tcuser"
    dockerhost.ssh.insert_key = false
  end
  config.vm.define "nginx", primary: true do |v|
    v.vm.provider "docker" do |d|
      d.vagrant_vagrantfile = "./Vagrantfile"
      d.vagrant_machine = "boot2docker"
      d.image = "russmckendrick/nginx"
      d.name  = "nginx"
      d.ports = ["80:80"]
    end
  end
end

As you can see, it is split into two parts: one for a Boot2Docker virtual machine and the second part for the container itself. If you were to run vagrant up, you would see something like the following terminal output:

The Vagrant Docker provider

As you can see, as I am using OS X, Vagrant knows that I can run Docker natively, so it takes the first section of Vagrantfile and launches a Boot2Docker instance. Boot2Docker is the tiny Linux distribution that powers Docker Machine's default driver.

Once it has downloaded the Boot2Docker Vagrant Box, it launches the virtual machine and maps port 22 on the virtual machine to port 2222 on our local PC so that we can get SSH access. Also, as defined in Vagrantfile, port 80 from the virtual machine is mapped to port 9999 on the local PC.

Its worth noting that if I were running this on a Linux PC that had Docker installed, then this step would have been skipped and Vagrant would have made use of my local Docker installation.

Now that Boot2Docker has been started, the second part of the Vagrantfile can be run. If, like in my case, Vagrant has downloaded and launched the Boot2Docker Vagrant Box, then you will be asked for a password; this is because we have not exchanged keys with the Boot2Docker virtual machine. The password is tcuser.

Once you have entered the password, Vagrant will download the NGINX image from https://hub.docker.com/r/russmckendrick/nginx/ and launch the container, opening port 80.

Once the container has been launched, you should be able to go to the NGINX welcome page at http://localhost:9999/.

If you like, you can SSH into the Boot2Docker virtual machine, as Vagrant is primarily managing the container and not the Boot2Docker virtual machine. You will have to use the following command:

ssh docker@localhost -p2222

Again, because we have not exchanged keys, you will need to enter the password, tcuser. You should then see this:

The Vagrant Docker provider

Once SSHed in, you will be able to run Docker commands locally. Finally, to terminate both the container and virtual machine, run the following command from within the same folder as your Vagrantfile and you will see something as following:

vagrant destroy
The Vagrant Docker provider

This will prompt you, asking whether you are sure you would like to remove the container and then the virtual machine; answer yes to both questions.

You must have noticed that we didn't cover our WordPress example while walking through the Docker provider. The reason for this is that the Docker provider functionality, in my opinion, is pretty much redundant now, especially as it has quite a few limitations that can all be easily overcome by using the provisioner or other tools.

One such limitation is that it can only use port mapping; we cannot assign an IP address to the virtual machine. If we did, it would have silently failed and reverted to port mapping from the virtual machine to the host PC.

Also, the functionality offered when launching containers doesn't feel as up to date and feature aligned to the latest version of Docker as the other tools we have been looking at so far in the chapter.

Because of this, I would recommend that you look at using the provisioner rather than the provider if you are looking at utilizing Vagrant.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset