Dockerized WordPress With Delectable Press

Dockerizing WordPress is no trivial task. My goal is for a multi-tenant setup — some being single sites, some being networks. The ability to “mutate” the application (ie, install plugins/themes) without actually mutating anything but the configuration. Something akin to compose/npm/paket/etc, where a simple file describes what you want installed and then it just happens.

Building that has been a challenge, and a ton of fun. You can find the first rendition on GitHub. The project is called Clam, while the orchestration tool will be called Pearl. Don’t ask why I chose such a stupid name, naming things is hard

I’ve spent the last week really digging in and building the infrastructure up. There’s still a lot of work to be done, which is documented in the issues.

How it works

There’s a lot of moving pieces in clam, some of which are still a little squeaky. If you want to play with it, go download Docker Toolbox and clone the repository. In your terminal of choice, run stacks/start-swarm.ps1 and sit back while Docker builds the underlying infrastructure on your machine.

I’m using docker swarm, for several reasons. The largest of which is that you can use a lot of the same nuances that are in production. But let’s not get into that.

Once the machines are built and running. Just type: docker-compose up -d It will immediately start downloading the most recently released containers (and hopefully the most stable). You can then visit to finish the installation of wordpress. (If you have any other docker-machine’s running, then the ip address I just mentioned will be wrong — type docker-machine ip manager to get the correct ip address).

You can now magically scale up and down using docker-compose commands and even view the logs as they stream. Here’s a little cheat sheet:

docker-compose scale php-fpm=3 — scales up the number of php instances to 3, giving you more throughput.

docker-compose scale nginx=3 — scales up the number of nginx instances to 3, giving more throughput.

docker-compose logs — stream the logs across your screen in realtime.

If you want to install a new plugin:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -e plugin=wpackagist-plugin/NAME_OF_PLUGIN clamp/srv-composer

Then edit the bottom of docker-compose.yml and add your newly built plugin… docker-compose up -d will make it so.

Yeah, you just realized that a plugin lives in its own container…

Each plugin and theme is isolated in its own container. It’s not what you might think, in that it doesn’t actually execute in that container… wouldn’t that be something cool? But since each plugin lives in a single container, it makes it easy to update/install plugins and themes across thousands of tenants. It also makes it so that there’s only one copy of any given plugin or theme on the disk. If there’s a change (e.g., someone got hacked), detecting it is very easy: docker diff will point it out very quickly.

This also allows tenants to have almost unlimited control of their installation in a complete sandbox without having to provision tons of vms or limit their ability to do whatever it is they need to do.

Future Challenges

  • Writing. Writing to the environment in a distributed fashion. Such as uploading images. That stuff will be hard, if not complicated. I have some interesting ideas I’d like to experiment with, but it will be a long time until I have time to work on those.
  • Scalable Caches. I’m experimenting with Rethinkdb as an object cache, as well as Redis. I’ll let you know how it goes.
  • Autoscaling. Knowing when to scale nginx, or php-fpm, or the cache…. and then doing it automatically and reliably. It will have to optimize for cpu and RTT … this part actually sounds really fun to me…
  • The Database. This one isn’t actually too hard. However, it seems like its going to be “busy work” and getting myself to actually sit down and do it … well, that’s a challenge.
  • Intrusion Detection. I really can’t wait for this one…

Want an inside scoop?

Check out PHP Shenanigans for only €5/mo or €30/yr