Docker the Vagrant Way
In addition to using orchestration tools like Ansible or Docker Compose, or your homegrown bubblegum and scripts with the
docker command, you can use Vagrant to orchestrate Docker containers in a virtual guest system.
Vagrant vs the World
There is one important distinction to draw here, between Vagrant and the other tools. The other solutions will use the underlying Docker system with the client tools exist on the host workstation. In contrast with Vagrant, the docker service (daemon) and Docker client tools exist on a separate virtual guest system.
Vagrant can use provisioners like shell or a change configuration platform like CF Engine, Chef, Ansible, Puppet, and Salt Stack, to provision the system. Docker is another provisioner in this example.
For the virtual platforms, Vagrant can use cross-platform FOSS (Free and Open Source Software) called Virtualbox or bundled solution like Hyper-V on Windows 10. Vagrant can also use others like VMWare, KVM, and cloud providers like AWS, Google Cloud, and Azure.
But the question that you may be asking, or at least should be asking, is WHY?!?!?
The short answer is control. You can create a clean development environment for Docker and other tooling, troubleshoot tool problems, reproduce bugs deterministically, and so on.
I occasionally use Vagrant to build out proof of concepts for variety of services, tooling, and especially when creating build tools and scripts CI/CD platforms.
The Problem Challenge
The goal or scope of exercise is to bring up a local WordPress service by deploying two containers. Below are the requirements.
Getting Started Code
I created a basic script to bring up an Ubuntu 16.04 image and embed a shell script download and install Docker, which is much faster than docker provisioner.
Download this below and save it as
Vagrantfile. Then try it out by running
vagrant up in the same directory.
I also included support for the environment variable
For implementation, you’ll need to add shell provisioning for the network and volume resources, as the docker provisioner does not have options for these.
For the docker provisioner, you’ll need to specify parameters that do not have an equivalent, which include passing environment variables, using network, mounting volumes, and specifying a container name.
If you would like to verify your solution works, I have created an Inspec script that you can use, and instructions below.
gem install inspec
gem install inspec-bin
Running the Script
As this the docker containers are running in a virtual guests, we have to log into that system through SSH. Inspec can remote into a system through SSH.
In order to do this, we would do something like this, depending on the output of
inspec exec \
-t ssh://firstname.lastname@example.org \
-i .vagrant/machines/default/virtualbox/private_key \
-p 2222 \
This is, well, cough, not intuitive, so I wrote a small helper script to help in this process:
Download this add the execute bit:
curl -O https://gist.githubusercontent.com/darkn3rd/44cf4c8bdbb9f063bba399e9e40c7189/raw/ec8698425d434abac05c5f76a612cfc9aa9e95dc/inspec_helper
chmod +x inspec_helper
Afterward, you can run the tests with the helper:
inspec exec $(./inspec_helper) container_test.rb
Testing with WORDPRESS_PORT
The current tests default to using port 8080 for testing the port. If you have changed the port through the environment variable
WORDPRESS_PORT, then you need to tell the test suite through InSpec attributes:
echo "port: $WORDPRESS_PORT" > attributes.yml
inspec exec $(./inspec_helper) tests --attrs=attributes.yml
Detailed Requirement Document
Below is a link to robust documentation on the requirements with explicit commands that can be used to validate the solution in POSIX shell like Bash.
Previous Shell Solution
This article might be useful for referencing a final solution. You could copy out these and use only the shell provisioner, and then replace the parts that Vagrant can manage with the Vagrant provisioner.
- Vagrant Docker Provisioner: https://www.vagrantup.com/docs/provisioning/docker.html
- Vagrant Shell Provisioner: https://www.vagrantup.com/docs/provisioning/shell.html
I added some automated Inspec automation to verify the solution that I hope some can try out. I put instructions to show how to have Inspec itself run the tests remotely through SSH, using the private key that is auto-generated by the Vagrant system. This latter bit is useful exercise in exposure to TDD (Test Driven Design) and possibilities for adapting your own frameworks or CI/CD pipelines to test systems.
I will follow up with an article on how to solve this and more.