Introducing DockPress

It is time to formally unveil the project that I have been working on for the past couple of weeks, clocking in at between 200-300 hours in a relatively short timespan.

The original plan was to get familiar with Kubernetes and refamiliarise myself with tools that I have used before. This resulted in something that other people in the WordPress space could use, especially those working in web development and system operation where reliability and resilience are important.

Enter DockPress

DockPress is a build-it-yourself Docker container, that installs and configures WordPress, PHP-FPM 8.1 and Nginx along with supporting libraries, application monitoring and facilities for WordPress object caching using Memched.

DockPress is meant to be forked and modified, so even if this project provides all the facilities for building an image using docker build -t dockpress, it is expected to be modified and built for every use case and pushed to a private repository.

A screenshot from Github, showing the repository the code base is stored in.

Features

One of the most important features built in to DockPress is the installation of the New Relic PHP agent. It is an extremely useful tool for application monitoring and has been invaluable for me when it comes to stepping in as a consultant and figuring out performance bottlenecks as well as privacy and security issues.

The second feature of DockPress it that is is designed with orchestration in Kubernetes in mind from day one, including the use of Kubernetes secrets to configure WordPress database credentials and other attributes that are usually read from wp-content.php.

The project’s Dockerfile provides several environment variables that can be utilised for customising your WordPress installation from adjusting PHP’s memory limits, uninstalling junk plugins included in the WordPress core, directing requests to files in the Media Library to an external CDN and compiling a custom build of ImageMagick and GhostScript for working with various image formats.

While working great as a standalone Docker container, it can be deployed to a Kubernetes cluster in the cloud relatively easily using the included documentation and YAML files, which should be approachable by anyone with some knowledge of cloud services and exposure to Kubernetes. (Those are intended as a platform-agnostic quick start and each cloud provider has its own way of handling this.)

Documentation goals

The aim is to make the Documentation easy enough to understand for intermediate and advanced WordPress developers to be able to use locally for development and testing and to deploy a Kubernetes cluster.

However, it will not replace Kubernetes’ documentation; or Google’s or Amazon’s specific documentation, even if there is going to be overlap.

Use it as a local development and testing environment

DockPress can be leveraged for testing and developing your plugins and themes using a fresh WordPress installation in a local Docker environment.

Simply spin up a MySQL or MariaDB server, add your database credentials to the file secrets/credentials.json and run the following command from the DockPress directory:

docker run --env MARIADB_ROOT_PASSWORD=my_amazing_password \
           --env MARIADB_DATABASE=wordpress \
           mariadb:latest

docker run -dp 80:80 \
  --mount type=bind,src=$(pwd)/secrets,dst=/secrets \
  --mount type=bind,src=/path/to/my/theme,dst=/var/www/html/wp-content/themes/mytheme \
  dockpress

But that is not what this post is about. However, it would be very interesting to see others using DockPress as a part of their development process. (Hint: A Docker Compose file is on the agenda, which would help here in case anyone wants to contribute one.)

Use it in a Kubernetes cluster

This is what this post is actually about. DockPress can spin up and configure a resilient and flexible WordPress installation that runs in the cloud using Kubernetes.

Kubernetes is a system for deployment, scaling, and management of containerised server applications that can run as a cluster. It can scale up and enable resilience during times of high server demand, conduct rolling restarts instead of taking everything down with it during maintenance and potentially saves costs by only using the resources that it needs when it needs it.

Dockpress includes basic documentation on how to deploy WordPress in a Kubernetes container with a simple service on port 80, including YAML files for persistent storage configuration, service exposure and deployment.

The documentation is oriented towards Google Kubernetes Engine but can be adapted to other cloud providers. (Hint: Google Cloud Services have a rather detailed instructions on how to do this properly with a managed TLS certificate, while currently the aim here is to provide more of a platform-agnostic quick start guide.)

In fact, this blog is running on a Kubernetes cluster. (Albeit, usually only running a single pod.)

The benefits of scalable WordPress using DockPress and Kubernetes

Traditional shared hosting is the way to go for most WordPress sites and I would not recommend anything else in most cases, for small businesses or bloggers.

Hosting your own cluster in Kubernetes is far from being beginner friendly but it is one of the best ways to ensure resilience and uptime when your online presence is crucial for your business.

Broadcasters, news organisations, online retailers, airlines, railways, universities, critical healthcare providers and the public sector should seriously consider hosting their websites in a resilient and failure-proof way and the benefits of using vertically scalable Kubernetes for such critical services can be invaluable.

Scalability for WordPress sites

Arguments about the vertical scalability and resilience of WordPress (or any other web framework or CMS for that matter) can usually be attributed to a lack of knowledge about how things work and of best practices.

Most of us are used to the pros and cons of traditional shared and dedicated WordPress hosting. Both ways have their issues with resource ceilings, which tools can be used effectively and communication lines if things fail.

Vertical scaling in the cloud means that your infrastructure does not need to be running at full speed 24/7. If you are dealing with sudden traffic rushes and periodical spikes, you only need to pay for the sufficient capacity to deal with the spikes as they happen, which in some cases results in lower costs.

Ownership and the chain of responsibility

In addition to being the only tenant on your own Kubernetes cluster, you gain clearer ownership of your infrastructure, can tweak the resource usage according to what you need and gain the stability and uptime you need when your web presence is your main source of income.

Not having to deal with a third party hosting provider and being able to deal with hosting issues in-house without information having to pass a filter can be extremely valuable when your daily revenue depends on your web presence.

Cloud friendly configuration management

On deployment (as a part of the entrypoint script), DockPress automatically creates a new wp-config.php file and populates it with values from the credentials.json file and performs other configuration actions such as configuring and installing the Memcached object cache, disabling automatic updates and file editing, filtering URLs for static assets to point to your CDN service and removing built-in plugins.

Here is an example credentials.json file:

{
    "mysql_server":       "10.123.80.3:3306",
    "mysql_db":           "wordpress",
    "mysql_user":         "root",
    "mysql_password":     "9YC&_BiN8y}5d'br",
    "new_relic_app_name": "",
    "new_relic_key":      "",
    "memcached_servers":  ["10.123.81.131:11211"],
    "memcached_key_salt": "38ukPY7GbqzRpkyxxU24JSMm",

    "auth_key":          "R[69McKM;cWxL_X0krBHU@c=FAEuK7,n~`,P_*^)g7d+}W3E^u(g}}B>kR|ewA*[",

    "secure_auth_key":   "2@Q}K08Wy(AjCF^Fa)JS{^*ZZ-sQ,S&~c`{%.Q(=Y{h$CXo@,0&vG~*pK6k51xgu",

    "logged_in_key":     "YG%ew+S;[c7>Up=r0FA{e ~!O%* 3T`li+{!]EbcQhk+-}j^Ae#bbUkZteFEuvG<",

    "nonce_key":         "%qtolv2;Nza]=RUjX9or$O@em<5X%!]z_$SG0,>R>?P|3li3 d@xU[22v@zv,y/K",

    "auth_salt":         "tX,J*^e2msSXY6ZA{FtYV_J~HD&nX7eBt-y&72f-W]-,~}J67zi@#8,@ix&QiPG=",

    "secure_auth_salt":  "5V>_?y?k06sTiD&/m-(L<Ad`uCP`q,dBjKoeCPpH*zBIB88;yT,yxBbtDaz;kU~p",

    "logged_in_salt":    "91yb?|%0zWSnU#`]) UgZFv5w=Y3$3=mY]TUVAs,8#Cz@YYy*>OgrktHj]Lcik/j",

    "nonce_salt":        "xL:g1=wU.TfO]{b0_xvuSSE0~a7:%rU?re6l[FYwmZb<G(5I4BRrVm&J<ccMyy@)"
}

This is a step up from depending on a static configuration file and leverages the Kubernetes secrets management system (or ConfigMaps if you want to go that route instead). It is as easy as the following to deploy once you have set up your Kubernetes cluster:

kubectl create secret generic credentials \
        --from-file secrets/credentials.json

Note that DockPress does not overwrite an already-existing wp-config.php file, unless it is forced to, as besides the deployment stage, DockPress is built with the assumption that your WordPress setup is immutable.

Leverage your cloud provider’s services

Every supporting service for WordPress can be spun up in the cloud. This includes the MySQL databases, file services, storage buckets and caching services. Virtual machines and individual Docker containers can be provisioned as well for the same roles in order to save costs.

Cloud hosting providers also provide advanced backup facilities for their customers. You can provision, monitor, move and restore your infrastructure on your own, so in case of your WordPress site being critical to your mission, monitoring and disaster recovery can be done in-house.

Instead of relying on a WordPress specific CDN service or a 3rd party proxy service, you can use your cloud provider’s own CDN facilities to serve static content faster to your users.

Monitoring and problem solving with New Relic

Generally, when assisting clients with ongoing issues, a typical WordPress consultant very often has little or no tools other than the server logs, educated guessing and an unclear description on the issue at had to go by; if anything.

On top of the monitoring tools used for keeping an eye on the cloud infrastructure itself, application monitoring can be a godsend to anyone monitoring different aspects of a web app, including WordPress sites.

With New Relic it is possible to follow up on things such as slow database queries, which plugin is the biggest bottleneck in your stack and even monitoring data egress for GDPR compliance and front-end performance issues.

This removes the guessing game that consultants and agencies, stops the blame shifting that may happen between clients, agencies and hosting providers and enables anyone in the chain of responsibility to know what is going on.

Hosting providers generally do not offer this tool or anything similar to their customers, except in the case of boutique offerings in the 500 EUR range by the likes of WPEngine, while running a small Kubernetes cluster and related services usually costs a fraction of that.

DockPress configures and installs New Relic as long as the New Relic App Name and Key attributes are set in your credentials file.

Immutability prevents code injection

In case of an automatic installation, DockPress assumes your WordPress installation (including the core, plugins and themes) to be immutable and that those files do not change, except during the next deployment or restart.

The most catastrophic failures for WordPress sites lie in code injection vulnerabilities in certain plugins and themes or user credentials ending up in the wrong hands.

This in combination with the official recommendation of giving the WordPress installation write access to itself in the name of enabling features such as automatic updates and the built-in plugin editor may result in all sorts of havoc and liabilities down the road.

Immutability also ensures that every pod in your cluster is running the same version of the WordPress core, plugins and themes if it is not running WordPress from a network volume.

The wp-content/uploads directory on the other hand is of course assumed to be writeable and needs to be a network volume in order to stay persistent (so that your files don’t disappear on restart.)

Image processing that just works

Some Linux distributions used by WordPress hosting providers do not allow ImageMagick — which WordPress depends on for image processing — to process PDF files and related formats.

DockPress compiles, installs and configures all the necessary underlying software such as ImageMagick and GhostScript for getting things such as image thumbnails and previews for PDFs working.

Run WordPress from a network volume

If DockPress does not find a WordPress installation in its expected location, it proceeds to download, install and configure a fresh installation of the WordPress Core as it starts up.

This is fine for the purpose of testing plugins and themes or to quickly spin up a momentary site that does not require any plugins or persistent storage — but for serious use, using persistent network volumes is the way to go.

GCS and AWS each offer their own flavours of NFS file servers that can be used for this purpose, in addition to backup and restore services. (You can also run a virtual machine for this as well if it sounds better for your budget.)

This enables you to retain the same WordPress installation and uploaded files between restarts and to fine-tune file system access according to your needs, especially in case absolute immutability is not what you need.

The readme file provides instructions on mounting local directories as persistent volumes in Docker. DockPress also includes documentation on how to provision network storage on Google Cloud and mounting the volumes in Kubernetes.

Use WP-CLI

As DockPress installs WP-CLI on each pod, it can be invoked by administrative users with access to the cluster using kubectl exec -it $pod_name -- wp cache flush --allow-root. where $pod_name is the name of one of the pods in your cluster. (In a local Docker setup, the docker exec command can be used.)

The only caveat here is that WP CLI will warn you if you are running the command as root (which makes sense to warn about in a traditional hosting environment but don’t worry about it here) so you will need to add the --allow-root flag to your WP CLI commands as you go.

Deployment challenges

The biggest technical challenge and the next big step in developing DockPress has to do with deployment. Many WordPress developers are still manually deploying and updating new sites to a traditional web hosting service by uploading files via (S)FTP or by using similar methods.

What is currently not included is an obviously documented way to deploy a site or plugin to a production DockPress instance.

This is how this site that you are looking at is currently being deployed:

  • A small Linux virtual machine mounts the same drive volumes as the DockPress pods (or is the file server itself).
  • An SSH key for that machine’s root user is kept as a Github Actions secret.
  • An automated process (via Github actions) is initiated when code gets merged into the main branch on Github and uses SSH to run a command or a script on the server that pulls the site, plugin or theme from Github.
  • The server also runs cron jobs for updates and security running on a VM.

In others words, this is not that complex using modern methods. It is just a question of getting started with using them — and knowing what you are doing.

I may document things and write further blog posts in the coming weeks or months.

Try it out and get involved

I would be happy to get input and feedback about this project. The Github repository is open to pull requests, issue tickets and forking — and non-programming tasks such as the documentation is are absolutely open to discussion and improvements.

I am also open to potential clients that are currently dealing with downtime and performance issues on their WordPress sites and would benefit from vertical scalability and application monitoring.