Local WordPress development environment using Docker compose

Docker can be used to create a local WordPress development environment that can be created and destroyed when needed. This article presumes you have docker installed locally and takes you through creating a docker compose configuration file that combines WordPress and MySQL container into a WordPress development environment thats accessible via localhost.

Docker compose configuration

The docker-compose.yml configuration file should be placed in the root of your project which is where you run docker compose commands from. The configuration file is basically just a list of docker containers (WordPress and MySQL) and how they are configured / connected together.

Lets create our docker-compose.yml configuration file in our project folder, we will tell docker-compose what version we are using (3.1 is the latest at the time of writing this article), we will then tell it what containers we will be using via the settings option which is currently empty.

# docker-compose.yml
version: '3.1'
# List of required containers/services
services:
  wordpress:
    # WordPress settings
    image: wordpress:php7.0-apache
  db:
    # MySQL settings
    image: mysql:5.7
  adminer:
    # Adminer settings
    image: adminer
  mailcatcher:
    # Mailcatcher settings
    image: schickling/mailcatcher

WordPress and Apache server

We will use the official WordPress container that comes with an apache web server installed that is accessible via port 80, when the docker container will download WordPress files into the web directory meaning all you need to do is run thought the WordPress install wizard to create an admin user, general site settings, and connect it to a database (that will be on a separate MySQL container).

If you are looking to use xDebug in your environment check out this snippet to install the xdebug extension on your wordpress container.

Lets add WordPress container into the list of services in our docker-compose.yml configuration file.

wordpress:
  image: wordpress:php7.0-apache
  depends_on:
    - db
  links:
    - db
  volumes:
    - "./www:/var/www/html/"
  ports:
    - "8080:80"
  expose:
    - "9000"
  restart: always
  environment:
    WORDPRESS_DB_HOST: db:3306
    WORDPRESS_DB_USER: wp_user
    WORDPRESS_DB_PASSWORD: pass

MySQL database

We have a WordPress container that will download the WordPress files but we still need a database, for this we will be using the official MySQL container runnign version 5.7 because using the latest version causes some issues, we make the MySQL database be persistent by mounting the /var/lib/mysql folder locally.

Lets add MySQL container into the list of services in our docker-compose.yml configuration file.

db:
  image: mysql:5.7
  volumes:
    - "./mysql:/var/lib/mysql"
  restart: always
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: wordpress
    MYSQL_USER: wp_user
    MYSQL_PASSWORD: pass
  expose:
    - '3306'
  ports:
    - "3306:3306"

Database Management using Adminer

We will be using adminer to manage our MySQL database, this will be accessible via localhost:8081

adminer:
  image: adminer
  depends_on:
    - db
  links:
    - db
  restart: always
  ports:
    - 8081:8080

Debug emails locally with Mailcatcher

The Mailcatcher image allows us to preview emails locally, todo this we need to configure WordPress to send all emails via SMTP to mailcatchers local SMTP Server, which we can then view via its email client interface accessible at localhost:1080.

mailcatcher:
  image: schickling/mailcatcher
  ports:
    - "1025:1025"
    - "1080:1080"

We can configure WordPress to automatically send all emails locally via mailcatchers SMPT server by adding the following file: mailtacher.php into the mu-plugins folder in the wp-content directory.

<?php
// www/wp-content/mu-plugins/mailcatcher.php
if ( ! defined( 'ABSPATH' ) ) die( header( 'HTTP/1.0 403 Forbidden' ) );

add_action( 'phpmailer_init', function( $phpmailer ) {
    $phpmailer->Host = 'mailcatcher';
    $phpmailer->Port = 1025;
    $phpmailer->SMTPAuth = false;
	$phpmailer->Encoding = 'quoted-printable';
    $phpmailer->isSMTP();
} );

Complete docker-compose.yml

Our complete docker-compose.yml file should look like the following

# docker-compose.yml
version: '3.1'
services:
  wordpress:
    image: wordpress:php7.0-apache
    depends_on:
      - db
    links:
      - db
    volumes:
      - "./www:/var/www/html/"
    ports:
      - "8080:80"
    expose:
      - "9000"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: pass
  db:
    image: mysql:5.7
    volumes:
      - "./mysql:/var/lib/mysql"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp_user
      MYSQL_PASSWORD: pass
    expose:
      - '3306'
    ports:
      - "3306:3306"
  adminer:
    image: adminer
    depends_on:
      - db
    links:
      - db
    restart: always
    ports:
      - 8081:8080
  mailcatcher:
    image: schickling/mailcatcher
    ports:
      - "1025:1025"
      - "1080:1080"

Runing the docker compose setup

Docker compose should be run from within the same folder as your docker-compose.yml file, using docker-compose run command in your favourite terminal it should start downloading and installing the required containers that we have configured, and allowing you to access the local web server via http://localhost:8080, if this is the first time you have ran this setup then the wordpress files will be downloaded and you should see the WordPress install wizard.

# Web server - http://localhost:8080
# Adminer - http://localhost:8081
# Mailcatcher - http://localhost:1080

# run docker-compose
docker-compose run