Before Docker came on the scene Vagrant was the go-to solution for creating development environments that can be configured independently of your machine and shared with a team. There are many benefits to using virtualization 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.
- Environments 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.
These days Docker has become the de facto solution for virtualizing development environments and devops in general. Docker works in a fundamentally different way from virtual machines by using containers to package code and dependencies together. 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 environment in each.
Vagrant vs Docker – High Level Comparison
Vagrant utilizes a much simpler architecture than Docker. It uses virtual machines (VMs) to run a virtual environment 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 the 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. They can also be slow to boot.
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 macOS, Windows, Linux, etc). Containers tend to take up much less space than virtual machines, normally weighing tens of MBs in size as opposed to tens of GBs.
If you’ve not used Docker in a while, one thing to note is that you no longer need to install Docker Toolbox to run a VM via Virtualbox. Docker now runs natively using HyperKit (macOS) and Hyper-V (Windows) making it much quicker and much easier to use than having to set up and connect to a standalone virtual machine.
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 disk 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 an open source 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. VVV also recommends you install the vagrant-hostsupdater plugin which automatically updates your hosts
file to access the provisioned VVV domains in your browser.
Now that we have all the prerequisites installed let’s clone the VVV repo to a local directory:
$ git clone -b master 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). To verify VVV has been installed correctly visit http://vvv.test. You should see a VVV dashboard page.
VVV sets up two default WordPress sites for you to use for development, http://one.wordpress.test and http://two.wordpress.test. You can use these sites for development by putting your themes and plugins in the relevant folder (e.g. www/wordpress-one/public_html/wp-content
). Or you can add a new custom site if you wish.
I recommend you read the VVV docs 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 Docker Desktop which provides everything you need to run docker containers on your local machine including the Docker engine, Docker command line, Docker Compose etc.
Next, we’re going to use the official Docker images for WordPress and MySQL to get our WordPress site up and running. We will run WordPress (which includes Apache and PHP) in one container and we will run MySQL in a different container as the database.
First, we need to create a docker network that our containers can use to communicate with each other:
docker network create wordpress-network
Next, create the MySQL container for our database:
$ docker run --name wordpressdb \
--network wordpress-network \
-e MYSQL_ROOT_PASSWORD=password \
-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 tell it to use the
wordpress-network
we just created. - We specify an
-e
environment variable that will be used by the container. This is a common way of passing configuration information to a container (setting the MySQL root password in this case). - 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.
Finally, let’s create a WordPress container:
$ docker run --name wordpress \
--network wordpress-network \
-e WORDPRESS_DB_HOST=wordpressdb \
-e WORDPRESS_DB_PASSWORD=password \
-p 80:80 \
-d wordpress
One thing we did here that we didn’t do for the MySQL container above is that we set up ports so that port 80
on our host 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 when you visit http://localhost (port 80
) you should see a WordPress install screen.
To start developing your WordPress themes or plugins you can attach them as a volume to the wordpress
container by passing a -v / --volume
flag when running the container:
$ docker run --name wordpress \
--network wordpress-network \
-e WORDPRESS_DB_HOST=wordpressdb \
-e WORDPRESS_DB_PASSWORD=password \
-p 80:80 \
-v ~/path/to/my-plugin:/var/www/html/wp-content/plugins/my-plugin \
-d wordpress
You should now see the plugin inside the WordPress admin.
Using Docker Compose
Running commands as 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:
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 80:80
environment:
WORDPRESS_DB_HOST: wordpressdb
WORDPRESS_DB_PASSWORD: password
volumes:
- wordpress:/var/www/html
wordpressdb:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
- database:/var/lib/mysql
volumes:
wordpress:
database:
You can see how we’ve just replicated the commands above into a yml
file using the compose file reference. Two differences from the commands above are:
- We don’t need to specify a network as Docker Compose will create one automatically.
- We specify
wordpress
anddatabase
volumes so that the relevant container data persists even when the containers are stopped.
To run the docker-compose file:
$ docker-compose up -d
Now, when you visit http://localhost you should see a WordPress install screen again. As before, we can add volumes for specific themes and plugins you want to develop:
volumes:
- wordpress:/var/www/html
- ./path/to/my-plugin:/var/www/html/wp-content/plugins/my-plugin
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 have been using Docker for a few years now and feel comfortable enough with it to use it on a regular basis for my development work.
What do you use for your development environment? Do you prefer Vagrant, Docker or something else?