back home

Dropping in a PHP container

Written by Bunkers on February 27, 2017

This is the fourth post in my series about running a Docker based WordPress development environment. Yesterday I left it in a bit of a strange state, but all being well, you'll have a docker-compose setup that manipulates two containers. One for the database and the other for our data, or application file system.

This doesn't do much, so today I want to add in our PHP container. This will mean we are able to process PHP code. In the next post we'll add the fourth, and final, container running NGINX as our web server. That will mean we have a full working PHP environment. So, let's start by looking at our PHP container.

I'd hoped that we could just use an official PHP image for the PHP container, but WordPress (and probably most other PHP applications) requires the installation of extensions like GD for images and the MySQL driver. So we need to create our own image, but as this is just using a Dockerfile it's simple to do.

Create a directory called php alongside our other two image folders, percona and site. In it create a file called Dockerfile with the following contents:

FROM php:7.1-fpm
# install the PHP extensions we need
RUN set -ex; \
    apt-get update; \
    apt-get install -y \
        libjpeg-dev \
        libpng12-dev \
                libcurl4-openssl-dev \
    ; \
    rm -rf /var/lib/apt/lists/*; \
    docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \
    docker-php-ext-install gd mysqli opcache curl 
# set recommended PHP.ini settings
# see
RUN { \
        echo 'opcache.memory_consumption=128'; \
        echo 'opcache.interned_strings_buffer=8'; \
        echo 'opcache.max_accelerated_files=4000'; \
        echo 'opcache.revalidate_freq=2'; \
        echo 'opcache.fast_shutdown=1'; \
        echo 'opcache.enable_cli=1'; \
    } > /usr/local/etc/php/conf.d/opcache-recommended.ini
VOLUME /var/www/html

This is more involved than some of out other configuration files, but the majority should be familiar from the site image's Dockerfile yesterday. It starts by taking the official PHP 7.1 FPM image and installing the required libraries using apt-get. The PHP image provides a command to enable the PHP extensions which is the next two lines. Lastly, we create a configuration file for OpCache. Enabling OpCache probably isn't strictly necessary, especially in a development environment, but it's good to show the principle and turning it off is as simple as removing opcache from the docker-php-ext-install command.

With this in place, we can add our PHP container to our docker-compose.yml. The contents of which should now look like this:

version: '2'
    build: ./percona
      - "3306"
    env_file: ./db.env
    build: ./site
      - ./db.env
      - ./site/wp.env
      - /var/www/html
      - ./wp-content:/var/www/html/wp-content
    build: ./php
      - data
      - percona:wpdb
    env_file: ./db.env

The new concept here is the links section. This is a list of mappings from other container names to a name you want to use locally within the container. In this case, I'm setting a reference name of wpdb to point to our percona container. This means we can use wpdb as the host name for the database in our wp-config.php file.

It's time to test our new setup. If you still have everything running from yesterday, in the project directory, run:

docker-compose down

Be careful with that command if you've done any work with the database container. It will stop the containers and delete them, so you will lose any data in the database! So far we've not put anything of worth in it, but if you've been experimenting then you might want to back up your data first.

Then, as before, run:

docker-compose up -d

You should see a number of messages about building your PHP image and then the steps it takes to install the modules and configuration from the Dockerfile.

Just to check everything is working correctly, run:

docker-compose ps

You'll see a table of our three containers. The data container that has got an Exit state, followed by our percona and php containers. These should both be Up and have information about the ports they're exposing.

Despite having to create our own PHP image, it's still got applications beyond running WordPress. I like this as we're sticking to the idea of having images and containers with a single use. It also means the images we're creating are reusable.

I'm conscious this still doesn't do a great deal, but I also don't want to dump too much information in one post. Once we get the web server running and hooked up to our PHP container in my next post, then you'll have a full PHP development environment. Until then!