It’s official. We are creating and maintaining a WordPress Docker image built on FrankenPHP, Caddy, & custom server caching modules.
I am excited about the opportunities that are now available with this release.
Get Started
Why Do It?
You may ask why another WordPress Docker image needed to be created. The standard Docker image is well battle-tested in production workloads.
But, it can be better.
1 Image as Fast as PHP-FPM + fastcgi
This single FrankenWP Docker image includes built-in distributed server caching through Souin & Caddy server that is just as fast as PHP-FPM + fastcgi. The benefits are that you only need 1 Docker Image, and the server cache can be mounted on as many autoscaled servers as you want.
Here’s a visual Comparing WordPress with Nginx + PHP-FPM Docker Compose to WPEverywhere FrankenWP.
Nginx + PHP-FPM Docker Compose File
FrankenWP Docker Compose
Notice the difference?
You don’t need 2 be running multiple containers, and you don’t have to create and mount custom configuration files.
1 image, and override configurations only when desired.
Performance at Scale
The goal of FrankenWP wasn’t to have the fastest WordPress server. I’m sure other configurations are faster. But, it did need to compete and perform at scale.
And it does.
I ran the FrankenWP Docker image in a Loader.io test with 10,000 requests in 1 minute and compared it with the standard Apache WordPress image.
The results show that the FrankenWP image can handle the load without issue, whereas the Apache image starts to error.
FrankenWP Image Loader.io with 10k Requests
Apache WP Image Loader.io 1,800 Requests (errors out on more)
Real-World Production Server Response Example
Here is an example of a production website running on the FrankenWP Docker image. They also use a prominent site builder plugin that is known to slow down sites.
What about PHP-FPM + Nginx comparison?
Indeed, the Apache image isn’t known to be the fastest option for deploying WordPress at scale. I wanted to compare one image to another, and this made the simplest test.
I may compare FrankenWP with Nginx + PHP-FPM or Litespeed, but this accomplished my goal of confirming that this image can run WordPress in production at a large scale.
Decreasing Costs in the Cloud
The challenges of scaling WordPress are all the optimizations required. You need opcache, cache plugins, Redis, fastcgi with PHP-FPM, and servers to handle the memory.
But what if you could deploy a single WordPress container into a $6 / month 1gb ram + 2 cpu server that can handle production workloads without extra configurations?
It’s possible.
The production instance above & load tests are running on a single t4g.micro ec2 in AWS. On-demand, it costs only $6 / month.
CPU Utilization averages less than 10% with peaks to 20%
Memory averages 30% utilization and peaks at 50% during higher traffic periods.
This single instance can reliably manage more than 100k+ monthly production visitors with first-rate user experiences.
What’s Going on Inside the Docker Image
There are a few core pieces that make up this WordPress Docker image:
- FrankenPHP
- Caddy Web Server
- Sidekick Server Caching Service
- Opcache
- Base WordPress Docker image
FrankenPHP
FrankenPHP calls itself the modern PHP application server written in Go. I agree with this claim. It compiles with a custom fast PHP c runtime in a Caddy Web Server. We do a unique build to pull in the Souin cache module, but FrankenPHP is what keeps us from needing PHP-FPM.
Caddy Web Server
Caddy is to Nginx, which is what FrankenPHP is to PHP-FPM. Caddy is the underlying web server that powers it all. It is written in go and takes advantage of the standout concurrency feature: Goroutines.
Caddy allows us to run concurrent PHP requests and other processes that can run in the background. We can send a response to the browser and execute a data processing job in the background.
Sidekick Caching
The Sidekick cache is a custom server caching solution we developed as a Caddy module. It stores content on-disk and in-memory to be distributed within sub-100 millisecond responses even in heavy load times.
The default cache is set to 8000 seconds but can be overwritten with a TTL environment variable.
The cache also includes a built-in REST API whenever you need to flush the entire cache or single pages. The API routes can be customized via environment variables, and I keep access to them only through the application.
WordPress Docker Image
We copy the WordPress content from the standard WordPress Docker image. This allows us to use the custom functions added to access the Docker environment variables in wp-config.php. It is also good practice as it helps us stay updated with the latest WordPress versions.
Ready to Get Started?
Checkout the github repo & Docker Hub images to start testing today.
Leave a Reply