Quick and easy WordPress development using Docker

TL/DR: Head over to this GitHub repo for a handy way to develop WordPress plugins and themes using Docker.

Update: Read about how I modified this Docker image to enable MultiSite.


I recently decided to create my first public WordPress plugin which provides basic FitBit stats for your blog.

This was on a fresh laptop (the one handily provided by Automattic, my new employer), so I had the opportunity to try something new in terms of my development environment.

I decided to try out Docker and the new Docker Compose tool (installation instructions – or just brew install boot2docker and brew install docker-compose).

Side Note: Docker, for those who don’t know, is a “container” runtime – a way of running Linux applications (even on OS X) that offers process and storage isolation but is lighter-weight than a full VM, allowing you to effectively run many different environments on the same computer. This is great for software development! I can test against 5 different versions of MySQL without having to somehow make them coexist on the same machine.

Sharing code with the Docker VM

This is the complex part of any Docker setup. We want to edit our code on the desktop and have the changes seamlessly appear when we reload the page. This means dealing with Docker volumes.

While boot2docker allows you to mount local directories as volumes (yay!), the mounted volumes can only effectively be written as root (boo! – but they’re working on it).

This is a problem for WordPress development because ideally your WordPress process (for example, Apache) needs permission to write to your plugin and theme directories. If it can’t, you need to install plugins and themes from the command line, which is fiddly and error-prone.

So why not run Apache as root? Alas, running Apache as root is not possible without recompiling the binary with the -DBIG_SECURITY_HOLE flag, and to be honest I’m too lazy to maintain a custom Apache binary. There must be a better way.

Some developers recommend the “data container” pattern, i.e. create a special container that persists data for sharing between your desktop filesystem and the Docker VMs, using something like samba. Frankly I couldn’t get it to work without crashing Finder, and it’s complex to understand and works poorly with Docker Compose, so it’s out as far as I’m concerned.

Eventually, after banging my head against this problem for a couple of days, the solution came to me just as I was falling asleep. It’s so obvious that I hated myself for not thinking of it earlier: Use PHP’s built-in web server to serve WordPress as the root user.

You can see the solution I came up with in my Docker image GitHub respository, but you don’t need to implement it yourself as I’ve now published the image in the Docker Registry. Read on to use it!

Booting the app

This is the easy part. Docker Compose gives us everything we need to initialize a new WordPress application. Create a new directory for this project (e.g. ~/workspace/wp) and create a file called docker-compose.yml with the following contents:

wordpress:
  image: gravityrail/wordpress
  volumes:
    - src:/var/www/html
  links:
    - db:mysql
  ports:
    - 8080:80

db:
  image: mariadb
  command: mysqld_safe --skip-name-resolve
  environment:
    MYSQL_ROOT_PASSWORD: example

Important to note that we override the mariadb command to include “–skip-name-resolve”. By default MySQL/MariaDB will try to look up the host name for an incoming IP address. Since composer doesn’t provide a hostname for our “wordpress” host to our “db” host, this can result in significant latency while DNS lookups are performed for every. Single. Query.

Then in the console, cd ~/workspace/wp and run the following command:

docker-compose up

Wait a few minutes while the containers are downloaded (they’re cached locally, so this only happens once) and then two services will boot – the WordPress container and MariaDB container. The logs will be output to your console.

During the boot process the WordPress image automatically installs WordPress to /var/www/html inside the container, so you should see the WordPress files magically appear in the src folder on your desktop!

Once booted (it only takes a couple of seconds) the service will be available at your boot2docker IP, port 8080. You can find it out like this:

boot2docker ip

Paste the output of that command into your browser (e.g. for me it’s http://192.168.59.103:8080/) and you should see the WordPress install screen.

Now you can edit the code locally and see your changes reflected instantly in your Docker WordPress instance.

Bonus: The wp cli command

I’ve included the wp-cli tool as part of the install (it’s how I boot the server), which means that from your desktop you can easily install plugins, manage the blog and database, and more.

For example:

docker-compose run wordpress wp --allow-root plugin install hello-dolly

Conclusion

I’m still experimenting with this configuration, but so far this is a super smooth workflow which has reduced the dependencies on my workstation and given me more flexibility. I’ll post again as this workflow evolves.

One Reply to “Quick and easy WordPress development using Docker”