back home

BASHing the WordPress Docker Container in to shape.

Written by Bunkers on March 1, 2017

This is the last post (for now) in my series documenting how I've setup a WordPress development environment with Docker. It really took shape yesterday when we got the full set of containers running. We've now got an environment that runs PHP code.

To finish up and get WordPress running we need to turn our attention back to the data container and its script. The full script is pretty involved, and there's a large amount that's lifted from the official WordPress Docker images, so I thought it's probably best to give you a [link to download it](link to download it), and just talk through the major points of interest!

In case you missed the links you can [download](link to download it) it and the rest of the files from GitHub here.

In our Dockerfile we downloaded and extracted WordPress to the /usr/src/wordpress directory. In this first section of the script we copy it over along with the database search and replace tool, if it's not already found. You'll nearly always get the warning about the directory not being empty as we've setup a link to the wp-content directory. I'm therefore considering removing that, or at least making the check more useful.

The file_env function is again taken from the WordPress image. I've seen it in a number of other Docker image entry point scripts, and allows environment variables to be setup from file names. The next section uses this to setup environment variables for the database.

We edit the wp-config.php file using the escape functions that follow. The WordPress official container is again the source for these! But the next section is new and looks for an environment value for WORDPRESS_MULTISITE. If found then the associated multisite configuration settings are setup from environment variables too.

The rest of the script sets up the wp-config.php if it's not found. The changes I've made from the official image script add in the settings for multisite if required. When setting up the file for the first time we add in the PHP define statements. When the wp-config already exists we use the set_config function to update the values as necessary. I haven't covered the situation where you want to turn multisite off in this script. The best solution would be to remove the container and have it rebuilt with the new configuration.

The set_config function updates all the other configuration options to finish the script. The one change I made here was regarding the unique keys and salts values. I wanted them to be more like the values you receive from the WordPress generator. Probably not necessary for a development environment but there's no harm in using it and it's one less thing to change for the production environment.

The change is with this line:

      set_config "$unique" "$(LC_ALL=C tr -cd '\41-\46\50-\133\135-\176' < /dev/urandom | head -c 64)"

We're calling set_config with our salt/key name, and the tr command filters the string of characters from the /dev/urandom device to remove non-printable characters. I know it gets escaped but I also filter out the apostrophe to avoid problems with it terminating the PHP string. The value used is the first 64 characters from this stream taken with the head command at the end. It's a small thing but creates a much more satisfyingly random string!

And that's the file for our data container. Feel free to suggest improvements. My BASH scripting skills are definitely not l33t standard.

There's a couple more things to add and update. Firstly we need another environment file called wp.env to contain our WordPress settings. This lives in the site directory for our data container and looks like:


or if you're using multisite:


You add this file in to the docker-compose.yml file by updating the data section:

    build: ./site
      - ./db.env
      - ./site/wp.env
      - /var/www/html
      - ./wp-content:/var/www/html/wp-content

These settings allow our container access to the database connection details and any additional WordPress config in the wp.env file. You may not have any additional WordPress configuration, in which case you don't need to bother with linking it in.

While we're editing it, there's one more change in the docker-compose.yml file that allows the PHP container to see our web container with the right domain name. This is important for upgrades as WordPress hits URLs on the site itself. Change the php section to:

    #image: php:7-fpm
    build: ./php
      - data
      - percona:wpdb
      - web:tutorial.bunkers
    env_file: ./db.env

We're linking our web server container to the PHP one with the domain name we're using so any requests to it get routed to the web server. The database environment variables are also added in for using the search and replace tool from the command line.

The last change is to our NGINX site.conf file. WordPress uses Apache's mod_rewrite to provide pretty URLs for posts. The rewriting rules are different for NGINX. They're also more complicated for multisite installs. Thankfully I discovered that the multisite setup will work fine for a single site install, so we can use the same configuration for both.

It's a big update to the file, so again just download it and don't forget to change the domain to fit your environment.

There we have it! You can now place a backup of the site in your wp-content directory and a backup of the database in the percona/tmp folder, bring up the containers with:

docker-compose up --build -d

This forces a rebuild of our images with the new file.

Load in the database using our load-db script, and you'll have a working development version of your WordPress site. Alternatively just start up the containers and when you go to your development URL you'll go through the WordPress install process for setting up a new site.

I'm sure I'll revisit this over time. I want to setup these images in a Docker registry so setting it all up is just configuration - a docker-compose.yml file and some environment variable files. I'd also like to expand it for use in a production environment, so if you're interested, watch this space!