If you’re learning web design, developing a WordPress theme is a great way to start—it’s a “proper” project that lets you bone up on your HTML and CSS skills, while giving you a very beginner-friendly introduction to PHP. It’s also a sometimes-rude introduction to the shenanigans of testing your theme.
You start with setting up a web server on your laptop, or in a virtual machine. Then, every time you make a change that you want to test, you have to add your theme’s files to your server, and poke at your website to test it. You repeat this a lot—whether you’re trying to test your styles across browsers, as your wishlist for your theme grows, or if you’re just learning new techniques to optimize the theme. Meanwhile, the WordPress team has now released a new update, and you should probably start testing your theme with that version again.
But there’s a better way: every time you make a change to your theme, you can automatically have a WordPress site up and running—with your theme ready—for you to test.
The Project: Testing a WordPress Theme
Let’s say you’re developing a WordPress theme, and you want to test it with the latest WordPress—it’d be great for your users if you could certify your theme with the latest version as soon as you can.
Ordinarily, you’d do something like this:
- Install PHP and a web server (Nginx, for example) on your laptop, desktop, or a virtual machine.
- Download the new WordPress, and manually set it up—copy it to the server, add your database information to wp-config, etc.
- From your GitHub repository, copy your theme to WordPress’s
- Open your site to poke at it.
This is annoying, or at least sub-optimal.
So here’s what we set out to do:
- Automate everything short of “poke at the site” with Distelli, so that you can get a testable version of the theme on a whim.
- Use Docker, so that this project can work on any Linux distribution, and doesn’t depend on what’s installed on the server.
- Experiment with some Docker best practices. Specifically, (a) keeping the image lean and (b) making the image “ephemeral”—meaning that the Docker container can be replaced by the next version of the container, and the application will continue to work as before.
To recap: Docker lets you package your application, all its dependencies, and all your environment settings into a single package, called an image, which can be saved to an online repository (such as Docker Hub or Amazon’s EC2 Container Registry). When you’re ready to deploy your application, you pull the Docker image to your server, and run the image as a container. Once your app and its dependencies are packaged into a Docker image, the app should run on any Linux server that supports Docker. In our recent post, Building Docker Images with Distelli, we talked about why delivering your application as a Docker image is a good idea.
The result of our effort is the WordPress Theme Tester Thing. The GitHub repository contains the Dockerfile, a blank WordPress theme, an Nginx configuration file, and the build and deploy steps you’d need to put into your Distelli application to set it all up.
For a detailed tutorial on how to create the project yourself, see Testing a WordPress Theme with Docker and Distelli.
Let’s take a high-level look at how this works.
Automating Stuff With Distelli
The first thing to do is to automate tasks with Distelli, using build and deployment steps. A quick summary: build steps let you configure your build environment so that your application can be successfully built—installing build tools, configuring prerequisites, and so on. Deployment steps let you ensure that on all your destination servers, your application’s dependencies are installed on and configured before the application is started. For example, for WordPress, you’d use the deployment steps to install Nginx and PHP on your destination server.
To automate tasks with Distelli, we start with creating a new application. Now, we need to set up the build—package all the code that we want to send to the server. Here’s how that build needs to go:
- Download and extract the latest WordPress files.
- Create a WordPress configuration file (
wp-config.php), and add your MySQL database details.
- Copy your theme to WordPress’s
- Package this all up to send to your server.
Now that we’ve set up a release package, we want to deliver it to our server, so that we can test it. On the destination server, we first install Distelli Agent. Then, we add an environment, and add our server to that environment.
Now, to set up the deployment:
- We’ll put our MySQL database name and password in our server’s environment variables, so that they’re not stored in the
- We’ll install Nginx and PHP (specifically, php-fpm) on our server.
- We’ll copy our release package (i.e. the WordPress files) to the default site folder for Nginx.
- Finally, we’ll start PHP-fpm and Nginx.
For steps to set up a build and deployment workflow using Distelli, see the Distelli User Guides.
All good so far. Now to add Docker.
With Distelli, we’re using the build and deployment steps using a mechanism to ensure that the destination server always has the programs that our application needs. Now, to make sure that any changes in the server don’t mess up your tests, we need to create a Docker image.
This means that we now need to create a Docker file, which defines what goes into the Docker image—such as dependencies, configuration files, and so on. This in turn means that some of our Distelli build steps need to be moved to the Docker image instead.
Creating the Dockerfile
At a high level, think of a Docker container as a destination server—because functionally, that’s what it is. When you start your app in a Docker container, it’s essentially replacing the ‘old way’ of starting an app on a bare Linux server.
Going by that guideline, your Distelli build steps remain mostly similar, because you can package your application outside the Docker container. Your deployment steps, however, now go into the Docker file. Let’s start with the Docker file, and work our way to the build and deployment settings we need to get that Docker file working.
First, the base image. This is the first building block of our Docker image. We’ve used Ubuntu as our base for experiments and demos, because it’s a familiar distribution that we use on our VMs, too. However, the base image is also quite large—around 188 MB. As a balance between familiarity and size, we used the
debian:jessie image, which still supports all the apt-get commands we like, but is about 51 MB.
Now, because we’re thinking of the Docker image as our destination server, let’s look back at our deployment workflow to decide what we put into the Docker file:
1. We’ll put our MySQL database name and password in the server’s environment variables, so that they’re not stored in the `wp-config` file.
This still applies—we don’t want environment variables to be stored in the Dockerfile either, so let’s come back to this when we’re setting up the Distelli application.
2. We’ll install Nginx and PHP (specifically, PHP-FPM) on our server. 3. We’ll copy our release package (i.e. the WordPress files) to the default site folder for Nginx. 4. Finally, we’ll start PHP-FPM and Nginx.
These steps are required to get the app running, so they need to go into the Docker file.
Setting up the Distelli Application
Now, we’ll use a Distelli application to automate all the prerequisite tasks—the steps to configure our WordPress installation:
1. Download and extract the latest WordPress files. 2. Create a WordPress configuration file (`wp-config.php`), which has your MySQL database details. 3. Copy your theme to WordPress’s `themes` folder.
These tasks don’t need to be run in the Docker container, so adding them to the Docker file creates unnecessary bloat. We’ll use Distelli’s build steps to automate the tasks, so that when the Docker image is built, it just copies the final WordPress files to the container.
And finally, the environment variables we held off on earlier. We need to make sure that:
- The environment variables are added to our destination server, and
- The environment variables are added to the Docker container when it is run.
To do this, we:
- Install Distelli Agent on the server (which in this case is a VirtualBox VM). For steps to install Distelli Agent, see Installing Distelli Agent
- Install Docker on that server. For steps to install Docker, see the Docker documentation.
- In the Distelli application, create an environment, and add the environment variables.
- Add the server to the environment.
- In the Distelli deployment steps, make sure that the environment variables are being passed to the container, by modifying the
sudo docker run $DISTELLI_DOCKER_PORTS --rm=true \ -e MYSQL_HOST \ -e MYSQL_ROOT_PASSWORD \ -e WP_DB_NAME \ -e WP_DB_USER_NAME \ -e WP_DB_USER_PASSWORD \ -e WP_AUTH_KEY \ "$DISTELLI_DOCKER_REPO:$DISTELLI_BUILDNUM"
And that’s it. If you enable automatic deployments, you can have a Docker container that has your theme up and running every time you make a change to the theme.
If you’re currently creating Docker images for your application, you can use the same approach to make your image leaner: offload prerequisite tasks to the Distelli build steps—for example, if you need to build a dependency from source.
More importantly, you can build your entire application outside the Docker image, so that you only need to copy the final release package—and not the source code—into the Docker container.
You can also modify this project for the following scenarios:
- Use it to test a WordPress plugin—you can adapt the build steps to copy your plugin’s files to WordPress’s
- Test your WordPress theme or plugin in a PHP 7 environment—instead of installing PHP 5 in the Docker container, you can download and install PHP 7.
- The Dockerfile, the nginx configuration file, and the commands to put in the Distelli build and deployment steps are in our GitHub repository.
- For a detailed tutorial on how to create the project yourself, see Testing a WordPress Theme with Docker and Distelli.
- For detailed information on the Distelli build and deployment steps, see the Distelli User Guides.