Vagrant vs Docker: Which is better for WordPress development?

#

For some time now Vagrant has been the go-to solution for creating development environments that can be configured independantly of your machine and shared with a team. There are many benefits to using virtual machines over installing software directly on your local machine (as MAMP does for example):

  • Software stacks are entirely independent from the machine you are working on.
  • Software stacks can be shared with other people and be reproduced automatically with ease.
  • Virtual machines can be started and stopped as required.
  • Hosting environments become ephemeral and can be thrown away when no longer useful.
  • It saves a lot of time.

Over the last couple of years, however, a new kid on the block has been gaining traction. While Docker also runs on a virtual machine it works in a fundanmentally different way. In this post we’re going to look at the difference between Vagrant and Docker and show you how to set up a WordPress development site in each.

Vagrant vs Docker – High Level Comparison

Vagrant utilises a much simpler architecture than Docker. It uses virtual machines to run environments independent of the host machine. This is done using what is called “virtualization” software such as VirtualBox or VMware. Each environment has its own virtual machine and is configured by use of a Vagrantfile. The Vagrantfile tells Vagrant how to set up the virtual machine and what scripts need to be run in order to provision the environment.

The downside to this approach is that each virtual machine includes not only your application and all of its libraries but the entire guest operating system as well, which may well be tens of GBs in size.

Docker, however, uses “containers” which include your application and all of its dependencies, but share the kernel (operating system) with other containers. Containers run as isolated processes on the host operating system but are not tied to any specific infrastructure (they can run on any computer).

What is the upshot of all of this?

  • Vagrant is easier to understand and is easier to get up and running but can be very resource intensive (in terms of RAM and space).
  • Docker’s architecture is harder to understand and can be harder to get up and running but is much faster, uses much less CPU and RAM and potentially uses much less space than Vagrant VM’s.

Setting up Vagrant

One of the great things about both the Vagrant and Docker ecosystems is that, due to the fact environments are easy to script and share, there are loads of great Vagrant “boxes” and Docker images already available to use.

In this case we are going to use a project called Varying Vagrant Vagrants (VVV) which is a popular vagrant configuration specifically designed for WordPress development. Before we begin, you will need both VirtualBox and Vagrant installed on your machine.

There are also several Vagrant plugins that VVV recommends you install:

  • vagrant-hostsupdater – Automatically updates your hosts file to access the provisioned VVV domains in your browser.
  • vagrant-triggers – Allows for various scripts to fire (such as database backups) when issuing commands such as vagrant halt and vagrant destroy.

Now that we have all the prerequisites installed let’s clone the VVV repo:

$ git clone git://github.com/Varying-Vagrant-Vagrants/VVV.git vagrant-local

Then we simply need to cd into the directory and run vagrant up:

$ cd vagrant-local && vagrant up

It will take Vagrant a while to download the required files, set up the virtual machine and provision it. (Note: if you’re using the “vagrant-hostsupdater” plugin you may be prompted for your password.) Once the provision script has finished you should be able to visit http://local.wordpress.dev and see WordPress! I recommend you read the VVV Readme for more information on how to set up and use VVV WordPress sites.

Setting up Docker

To get started with Docker first you need to install the Docker Toolbox which provides you with not only the Docker Client, but also Docker Machine (which controls the Docker Engine, previously boot2docker) and Docker Compose (which allows you to specify a multiple container setup in a single file) as well as some other bits and pieces.

Once you have it installed, the first thing you need to do is set up a Docker Virtual Machine. Docker will use this virtual machine to run the Docker Engine which manages any containers that you want to run. To do this let’s create a Docker Machine using VirtualBox called “docker-vm”:

$ docker-machine create --driver virtualbox docker-vm

Once the machine has been created we can check the details of the machine by running:

$ docker-machine env docker-vm

It should output something similar to:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/gilbitron/.docker/machine/machines/docker-vm"
export DOCKER_MACHINE_NAME="docker-vm"
# Run this command to configure your shell:
# eval "$(docker-machine env docker-vm)"

You’ll notice that these are actually commands that set environment variables for the Docker Client to communicate with the Docker Engine. So we do as we are told and run:

$ eval "$(docker-machine env docker-vm)"

Top tip: Every time you open a new session you will need to run this eval command as these settings don’t persist. So to save you this hassle you can add the eval command to your ~/.bashrc file so that it is run automatically every time you open a new session.

Now we are finally able to start creating Docker containers. One important thing I should point out here is that Docker encourages running only one process per container. This means that technically if we were running a LAMP stack, Apache, MySQL and PHP-FPM should all be run in their own containers. These, however, are only guidelines and in most cases it’s fine to group relevant processes together (for example Apache and PHP would normally run in one container, and MySQL in another container).

Thankfully there are official Docker images for both WordPress and MySQL that we are going to use. We will run WordPress (which includes Apache and PHP) in one container and we will run MySQL in a different container as the database.

To create a MySQL container run:

$ docker run --name wordpressdb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress -d mysql:5.7

You can have a look at the docker run reference to see what each of these flags does in detail but here is a quick rundown:

  • We give our container a --name so we can link to it later (if we didn’t specify this a random name would be generated).
  • We specify two -e environment variables that will be used by the container. This is a common way of passing configuration information to a container.
  • We tell the container to run in detached mode.
  • Finally we specify the image:version we want to use. If the image doesn’t exist locally it will be downloaded.

Next let’s create a WordPress container:

 $ docker run --name wordpress -e WORDPRESS_DB_PASSWORD=password -v "$PWD/":/var/www/html --link wordpressdb:mysql -p 80:80 -d wordpress

There are two things we did here that we didn’t do for the MySQL container above:

  • We specified a -v volume to map our “Present Working Directory” to the /var/www/html folder inside the container (note that $PWD could be an absolute or relative path as well). This allows us to manipulate the WordPress files.
  • We --linked this container to our wordpressdb container and gave it an alias mysql. This allows the WordPress container to connect to the MySQL container.
  • We set up ports so that port 80 on our virtual machine points to port 80 in the Docker network (which will be this container).

We can check the status of our containers by running:

$ docker ps

Now you can simply visit the IP address of your Docker Machine (you can find the IP address by running docker-machine env docker-vm like we did above and looking at the DOCKER_HOST value) et voilà you should see a WordPress install screen. Now would be a good point to add a local domain to your hosts file so you don’t need to use the IP address all the time. You should also see the WordPress files in your $PWD as we set it up as a volume earlier.

Bonus: Use Docker Compose

Running commands like we did above can be quite cumbersome and prone to human error. Docker Compose can help us out as it allows us to specify a single file in which we can define our entire environment structure and run it with a single command (much like a Vagrantfile works).

Let’s create a docker-compose.yml file:

wordpress:
  image: wordpress
  environment:
    - WORDPRESS_DB_PASSWORD=password
  ports:
    - "80:80"
  volumes:
    - ./:/var/www/html
  links:
    - wordpressdb:mysql

wordpressdb:
  image: mysql:5.7
  environment:
    - MYSQL_ROOT_PASSWORD=password
    - MYSQL_DATABASE=wordpress

You can see how we’ve just replicated the commands above into a yml file (using the compose file reference). Now all we need to do is run:

$ docker-compose up -d

So Which is Better?

As with all things of this nature there is no “right” and “wrong”, “better” or “worse”. It depends entirely on how you want to use it and what you feel comfortable with. I personally dabbled with setting up a Docker development environment recently but decided it was just too complex to get things working the way I wanted. I’m happy using Vagrant for the time being as it’s simple and just works, but I’ll be keeping an eye on Docker as the project matures and things will no doubt become easier.

What do you use for your development environment? Do you prefer Vagrant, Docker or something else?

About the Author

Gilbert Pellegrom

Gilbert loves to build software. From jQuery scripts to WordPress plugins to full blown SaaS apps, Gilbert has been creating elegant software his whole career. Probably most famous for creating the Nivo Slider.