A new tech stack for WordPress

A solid blog starts with a solid foundation - in this case WordPress and the tech stack that powers it.

I got my start in blogging thanks to WordPress. A friend talked me into attending a local WordPress event, and the rest is history. Since then I dabbled with various installations to keep my website alive, and the solutions evolved along with the times.

The early days of blogging had me renting a (too-expensive) virtual private server from a company in Canada. I then moved to a cheaper but less stable shared hosting package. I experimented with managed hosts like WP Engine and Pantheon, then went back and forth with smaller servers at Linode and Digital Ocean.

The last time I ran a site, it was through a heavily discounted friends-and-family plan with another shared host. Each time I’ve created a blog, I’ve either built an over-engineered system or settled on somewhat expensive managed hosting.

WordPress doesn’t need either of those.

My WordPress stack

This new site runs on WordPress, but in a way you probably don’t expect. Rather than build out a full LAMP or MAMP or *AMP stack, I’ve settled on Docker. WordPress itself is running as a PHP application inside a Docker container. Alongside it is Memcached, also in a Docker container, for an efficient object cache so the admin interface is snappy and quick. Then comes Varnish, again in a Docker container, so the front-end of the site is cacheable and delivered quickly.

All of this is running on an Amazon EC2 server, but really the hardware doesn’t matter that much. Docker containers can run on AWS, on Microsoft Azure, on Google Cloud. I choose AWS for my familiarity with the platform, not for any particular feature.

The server itself is behind a load balancer, which handles TLS termination for my security certificate and can, itself, be placed behind CloudFront if I want another layer of caching.

My advantage here is that, through containerization, my entire stack is portable. I can run my entire site on Amazon, or Google, or Microsoft, or locally with zero configuration changes based on the environment. I can scale up as needed (thanks to the load balancer) or back down when traffic drops. Finally, things are cheap.

The load balancer is actually the most expensive element of my stack – it’s ~$9/month. My entire server behind the load balancer runs $2/month and, frankly, I could probably do away with the load balancer if I wanted to.

Docker to the rescue

When I attend events, someone always asks folks to raise their hands if they use Docker in production. Then they shake their heads and deliver some condescending remark about bravery.

I’ve never understood that.

I have successfully used Docker, in production, at my day job for years. We run our entire system on containerized infrastructure. We handle millions of requests each minute and power the economic engine that drives the company forward successfully. In addition, we’ve proven that containerization allows our dev team to tear down and rebuild our entire infrastructure – from scratch – in minutes.

Honestly, if you’re not using Docker in production you’re behind. That’s why I built this site on Docker.

At the time of this writing, I’m on a single server using a docker-compose.yml file to build out my stack:

services:

  wordpress:

    image: wordpress

    depends_on:

     - db

     - memcache

    environment:

      WORDPRESS_DB_HOST: db:3306

      WORDPRESS_DB_NAME: wordpress

      WORDPRESS_DB_PASSWORD: thisisasecret

      WORDPRESS_DB_USER: thisisasecret

    restart: always

    volumes:

     - wordpress_data:/var/www/html



  memcache:

    image: memcached:alpine

    restart: always



  db:

    image: mariadb

    environment:

      MYSQL_ROOT_PASSWORD: thisisasecret

      MYSQL_DATABASE: wordpress

      MYSQL_USER: thisisasecret

      MYSQL_PASSWORD: thisisasecret

    restart: always

    volumes:

     - db_data:/var/lib/mysql



  varnish:

    build: ./varnish

    depends_on:

      - wordpress

    restart: always

    ports:

      - "80:80"

volumes:

  db_data: {}

  wordpress_data: {}

From here, scaling is relatively straightforward as the site grows:

  • Move the database out to its own instance – Amazon RDS will be my first choice
  • Move the cache (Memcached) to its own instance – Amazon Elasticache will be my first choice
  • Introduce CloudFront in between the public Internet and the load balancer
  • Move the Docker container for Varnish and the site to a serverless host – Amazon Fargate, for example
  • Move the filesystem for uploads to an external source – Amazon EFS or S3

The stack can evolve as the site grows to take in more traffic, but the core is still the same – encapsulating individual components of the project so they can be broken apart and replaced as needed. Today I manage a server, but the goal is to move to a managed, serverless system down the road so I can focus on just writing.

Everything old is new again

When I started with WordPress, the technology looked the same. WordPress itself ran in PHP behind either Apache or Nginx. The database was MySQL with Memcached as an object cache. Varnish often sat in front of everything as a streamlined front-end cache.

The difference is in the how. The old stack was all running either on a single server that had to be painfully maintained or offloaded to an expensive managed host. The new stack can leverage containers within a completely disposable single server or offload to managed components.

Seeing how the WordPress I know and love from a decade ago can grow and evolve into the kinds of modern infrastructures that efficiently power multi-billion dollar enterprises is incredible and hugely satisfying. I look forward to seeing how the tech – and the stack that powers this site – will continue to evolve!