A modern workflow for WordPress using Docker and Dokku

Dokku + WordPress

Every developer, sooner or later, had to deal with WordPress, given it is one of the most popular Blog/CMS platform, if not the most popular.
According to Wikipedia, roughly 22% of the web sites run on it, (it means one web site in five) it is widely know by users, it has a large community (over 30 thousand contributed plugins) and it is easily supported by designers.

Unfortunately WP was targeted at non-developer people, it had a great success as hosted platform, but working with it from the developer perspective, especially if we look at the workflow, looks clunky and outdated.

Usually it involves:

  • downloading a tar ball of the latest WordPress stable version
  • rename wp-config-sample.php to wp-config.php
  • if you’re using git (and you should!), add the wp-config.php to .gitignore
  • open a connection (possibly not FTP, but probably it will be FTP) and (slowly) upload everything on the dest server
  • create a remotewp-config.php with the production configuration
  • launch the installer
  • hope nobody will overwrite wp-config.php with the local copy

On the other hand, modern workflows are built around some kind of version control system (usually git) where the deploy is managed just by pushing a branch on the public server.
This is called push-to-deploy and is the one used by Heroku.
Fortunately, some smart guys created Docker and Dokku, two projects that make possible to build you own personal-heroku-like PaaS in a matter of minutes (If you want to try it, Digital Ocean offers cloud servers with Dokku preinstalled at a starting price of 5$/month).
Let’s see how it applies to WordPress.

In the rest of the article I’m going to use a few placeholders

  • app is the application name
  • dokku is the address (or hostanme if configured) of the destination server running Docker & Dokku
  • dokku-user is the user running Dokku on the remote machine

First of all we’re going to clone WP from github

git clone git@github.com:WordPress/WordPress.git app

Then we create wp-config.php, replace the configuration parameters with environment variables, and commit it.
This way we won’t have to hardcode them.

same technique can be used to configure the security keys, I didn’t, to keep things short.

define('DB_NAME', getenv('WP_DB_NAME'));
/** MySQL database username */
define('DB_USER', getenv('WP_DB_USER'));
/** MySQL database password */
define('DB_PASSWORD', getenv('WP_DB_PASS'));
/** MySQL hostname */
define('DB_HOST', getenv('WP_DB_HOST'));
git add wp-config.php
git commit -m 'added WordPress configuration'

If you use Apache, you can set the values with SetEnv, if you’re running Nginx and phpf-pm, you can use the ENV section of your application pool.
You don’t need any of that when deploying through Dokku.

For our first deploy, we need to add a new remote pointing at the Dokku server

git remote add dokku dokku-user@dokku:app

and push the code

git push dokku master

You will see something like this

Counting objects: 163187, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (33726/33726), done.
Writing objects: 100% (163187/163187), 84.87 MiB | 4.95 MiB/s, done.
Total 163187 (delta 128758), reused 163156 (delta 128730)
-----> Building app ...
PHP (classic) app detected
-----> Bundling NGINX 1.4.3
-----> Bundling PHP 5.5.5
-----> Bundling extensions
-----> Setting up default configuration
-----> Vendoring binaries into slug
-----> Discovering process types
Default process types for PHP (classic) -> web
-----> Releasing app ...
-----> Deploying app ...
-----> Cleaning up ...
=====> Application deployed:
To dokku@dokku:app
* [new branch] master -> master

As you can see, everything is already bundled with the PHP buildpack.
Dokku has detected the PHP app and instructed Docker to create an isolated container that could run the application.

You can now open up a browser and point to app_url (it can have two formats: http://ip_adress:port or http://app.defaultdomain. Either way, it should launch your app).

Our wp-config is empty right now, the server will reply with

WP Error

That’s good news, it means it is actually responding to our request.

To finish our setup we need a couple more things:

  • create a database
  • configure the app environment with the credentials

To create a db in our app container, we’ll use the MariaDB plugin for Dokku.
There’s also a MySQL plugin, but it has some annoying bug and since MySQL and MariaDB
are virtually identical, we’ll stick with the last one.
Installing a plugin for Dokku is as easy as running

cd /var/lib/dokku/plugins
dokku plugins-install

Some of them don’t require the final plugins-install step, but it won’t hurt if you run it anyway.

Tip: you can run dokku commands on your local machine and execute them on the remote one with:
ssh dokku-host dokku-command (i.e. ssh dokku help)

We can now create the database

ssh dokku mariadb:create app
-----> Creating /home/dokku/app/ENV
-----> Setting config vars and restarting app
DATABASE_URL: mysql2://root:VQpzDZRrEUAkUuAI@
-----> Releasing app ...
-----> Release complete!
-----> Deploying app ...
-----> Deploy complete!
-----> app linked to mariadb/app database
-----> MariaDB container created: mariadb/app
Port: 49170
User: 'root'
Password: 'VQpzDZRrEUAkUuAI'
Database: 'db'

and set set the Environment variables

# the format is dokku config:set app key=value key=value
# I splitted up the command on different lines for clarity
ssh dokku config:set app WP_DB_HOST=''
ssh dokku config:set app WP_DB_NAME='db'
ssh dokku config:set app WP_DB_USER='root'
ssh dokku config:set app WP_DB_PASS='VQpzDZRrEUAkUuAI'

If everything went right, you should now see the standard WordPress install.
Choose a title, create an admin user and you’re ready to go.
You can work on your local copy, add plugins, work on your theme, and when you’re happy with it, you push all the changes and the app is automatically deployed and configured.

We just scratched the surface of what is possible with Docker & Dokku.
In a next article we’ll see how to create a Dokku plugin to automate the entire process.

Leave a Reply