Logo

Navigation
  • Home
  • Android
  • Web
  • Raspberry Pi
  • PHP
  • Go

WordPress development with Docker Compose

By Rajinder Deol | on February 26, 2017 | 6 Comments
PHP Technology Web

I have been using Docker containers from last 2 years and I absolutely love using them in all my projects. Docker containers have a lot of benefits for development but I would like to highlight few :

  • Rapid application deployment :

    Docker containers can only have minimum components required for the application which means reduced size and that allow them to be deployed quickly

  • Portability across machines :

    An application with all its dependencies can be bundled into a container and that can be run in any OS/machine which has docker installed.

  • Version control and component reuse :

    Just like code we can track versions of our containers, compare difference between two versions and rollback to old version

  • Sharing :

    We can push out containers into a registry and share them with others. DockerHub is a public registry.

From here onwards I assume that you know what Docker is and how to write DockerFile. If you don’t, then do a quick read at docker docs.

You need to install Docker and Docker-compose on your system. We will write linux shell like commands in DockerFile for setup of our container. We will also use docker-compose.yml file to bind our different containers together. For further information please read Getting Started Guide on official docker site.

I customize my own blog quite a lot and I have created few custom plugins for my own use. During wordpress plugin development initially I have created my own custom Dockerfile to build and run my Docker container running Linux, Apache, MYSQL and PHP. But wordpress has released their official docker image on DockerHub so I have started using the official wordpress docker image.

Since past one year I came across few common problems while developing wordpress plugins under docker container and after solving them one by one, I ended up having a standard “day zero” wordpress docker-compose based setup.

This setup has bare minimum directories and files which we need for our development. Lets Start creating this setup step by step.

Step: 1 – Folders and directories

To well organize the project and avoid any confusion while development we will create two directories in our project

  • docker:

    To hold all our common docker files like wordpress and MYSQL

  • wp-content:

    This folder will have our plugin or theme development code

Step: 2 – DockerFiles for wordpress and MYSQL

WordPress docker image does not have database setup and needs an active database running to connect to. So we will first create our database container. I have decided to use MYSQL but you can use mariaDB as well.

  • Create folder “mysql” inside docker directory
  • Create an empty file named “DockerFile” inside mysql folder
  • Add the following code in the DockerFile:

    
    # MYSQL
    FROM mysql:5.7
    MAINTAINER Rajinder Deol <deol.rajinder@gmail>
    
    ENV MYSQL_ROOT_PASSWORD wordpress
    ENV MYSQL_DATABASE wordpress
    

    This DockerFile will build the MYSQL database and ENV MYSQL_ROOT_PASSWORD, ENV MYSQL_DATABASE will set the password and database name. We will use these values in out wordpress Dockerfile

After creating the database DockerFile, now we will move on to wordpress DockerFile.

  • Come back to the docker directory and create a new directory named “wordpress” inside it.
  • Now create a blank file named “DockerFile” inside the wordpress directory.
  • Add the following code in the DockerFile:

    
    #wordpress
    FROM wordpress:latest
    

Step: 3 – Docker Compose to link both the wordpress and MYSQL containers

So far we have created two DockerFiles in docker/mysql and docker/wordpress within our project folder for mysql and wordpress. Now we will use docker-compose to link these two containers with each other. Docker Compose also help us to run these two containers with single command and manage their properties from a single file.

Docker compose requires docker-compose.yml file to read the configuration and build and run the containers. Lets create our docker-compose.yml file:

  • In the project folder create an empty file named “docker-compose.yml”
  • Add the following code to configure MYSQL container :

    
    ## wordpress container.
    # wordpress MYSQL database
    database:
      build: docker/mysql
      # so that I can access it within 
      # mysqlworkbench on my machine
      ports:
        - "3306:3306"
      environment:
        - MYSQL_USER=wordpress
        - MYSQL_PASSWORD=wordpress
    
    

    This configuration will execute the DockerFile in docker/mysql folder. It will also forward the port 3306 on my host machine to port 3306 of container. This will help me connect to MYSQL database with MysqlWorkBench installed on my machine. We have also set the environment variables used by MYSQL container to create user with password.

  • Now we will add configuration for wordpress container.
  • Add the following code under the MYSQL configuration in the docker-compose.yml file:

    
    wordpress:
        links:
        # to access database container
        - database:database
        build: docker/wordpress
        # I dont want to block my port 80 as 
        # I run other containers which are forwarded to port 80
        ports:
           - "8000:80"
        restart: always
        volumes:
          # So that my plugin development in wp-content maps to container wp-content
          - ./wp-content:/var/www/html/wp-content
        environment:
           WORDPRESS_DB_HOST: database:3306
           WORDPRESS_DB_PASSWORD: wordpress
    
    

    This configuration will build the DockerFile located at docker/wordpress

    I have forwarded port 8000 of my machine to port 80 of the wordpress container. You can use port 80 but I usually run more than one application on my system which require port 80 to be available so I used port 8000.

    We have linked the MYSQL container with wordpress via links: attribute in the configuration. WordPress requires environment variables WORDPRESS_DB_HOST and WORDPRESS_DB_PASSWORD to access database.

    WordPress container has wordpress codebase installed in /var/www/html/ directory inside the container. To retain our development code during container restarts we have mounted our project “wp-content” folder to container’s /var/www/html/wp-content folder under volumes: attribute of wordpress configuration.

Step: 5 – Build and Run wordpress container

Make sure docker-compose is installed on you machine along with docker. Go to your project directory and run the following command:


docker-compose build

This command will download the wordpress and MYSQL docker images from the DockerHub and build your containers.

Now run:


docker-compose up

This command will fire up MYSQL and wordpress container. Once containers are up and running you will be able to access your fresh wordpress site at http://localhost:8000

Step: 6 – Default wordpress data for MYSQL container

By default the MYSQL container will not retain the wordpress data and when you will restart the containers you will again find the default install screen of wordpress.

You can solve this by mounting a volume for MYSQL container, however for most of my development I need basic installed wordpress with some default data to work with the development

So I have created a sql file named “wordpress_data.sql” with default data, inside the docker/mysql folder.

MYSQL container will import any sql file placed inside the /docker-entrypoint-initdb.d/ directory. So I have updated the mysql DockerFile and added an additional line to add this file to /docker-entrypoint-initdb.d/ directory. Now the mysql DockerFile should look like:


# MYSQL
FROM mysql:5.7
MAINTAINER Rajinder Deol <deol.rajinder@gmail>

ENV MYSQL_ROOT_PASSWORD wordpress
ENV MYSQL_DATABASE wordpress

# wordpress basic sql to start with
# MYSQL will import the sql file at startup
ADD wordpress_data.sql /docker-entrypoint-initdb.d/

Now with every docker container rebuild or restart, I will have my default data loaded in wordpress. Having the default data will also help to test the plugin or theme which we are developing.

Step: 7 – Proper file permissions of wp-content folder so that you can use your favorite editor

When the container is up and running, user www-data is set as owner of the wp-content folder. www-data is apache user which will access the wordpress content when site is loaded. However this will not allow us to edit the content of wp-content folder from host machine.

Although we have mounted our project’s wp-content folder to the container’s /var/www/html/wp-content folder but due to www-data being the owner of this folder we will not be able to edit the files inside this folder.

The solution is to create a user inside the container which has our UID and allow it to read/write the /var/www/html/wp-content folder.

To make it reusable on any machine, I cannot hardcode the UID of current user, so we will dynamically export the UID of current user into UID variable.

Run the following command:


   export UID=$(id -u $USER)

There is a default USER environment variable which hold the user name of current logged-in user. We will use these variables in our docker-compose.yml file and create two environment variables to be used inside wordpress container.

Now the wordpress configuration block in the docker-compose.yml file should look like :


 wordpress:
    links:
    # to access database container
    - database:database
    build: docker/wordpress
    # I dont want to block my port 80 as 
    # I run other containers which are forwarded to port 80
    ports:
       - "8000:80"
    restart: always
    volumes:
      # So that my plugin development in wp-content maps to container wp-content
      - ./wp-content:/var/www/html/wp-content
    environment:
       WORDPRESS_DB_HOST: database:3306
       WORDPRESS_DB_PASSWORD: wordpress
       LOCAL_USER_ID: $UID
       LOCAL_USER_NAME: $USER

We have added two environment variables LOCAL_USER_ID and LOCAL_USER_NAME which will be availabe inside the wordpress container.

I have created a shell script to use these variables and create the user. This script will also add the appropriate permission for this user to read/write /var/www/html/wp-content folder.

The script file is named as setuser.sh and it is placed under docker/wordpress folder of our project. The file contains following code:


#!/bin/bash

USER_ID=${LOCAL_USER_ID:-9001}
USER_NAME=${LOCAL_USER_NAME:-hostuser}

echo "Starting with UID : $USER_ID and UNAME : $USER_NAME"
echo "create $USER_NAME group if it doesnot exists"
getent group $USER_NAME || groupadd $USER_NAME
echo "create Adding User to group"
id -u $USER_NAME || useradd --shell /bin/bash -u $USER_ID -o -c "" -G $USER_NAME -m $USER_NAME
setfacl -R -m g:$USER_NAME:rwX /var/www/html/wp-content

Now we have to figure out a way to execute this script when wordpress container starts.

Unlike MYSQL container wordpress container does not have an option to run custom scripts during startup of the container. WordPress container has a docker-entrypoint.sh file which it executes to setup the container. The trick is to add a line in it at runtime to run our script right before it starts the apache.

After looking at the docker-entrypoint.sh and DockerFile I found that docker-entrypoint.sh file is copied to /usr/local/bin/ directory and then it is executed at the runtime so all I need to do is add a line in this file right before it executes the apache start command to run our setuser.sh file.

Lets update our wordpress DockerFile located in docker/wordpress folder and add the code. Now the DockerFile should have following code:


#wordpress
FROM wordpress:latest
COPY setuser.sh /var/www/html
RUN chmod +x /var/www/html/setuser.sh
# hacking into wordpress entry file 
# and adding my script right before the exit
RUN sed -i '/^exec "\$@"/i sh /var/www/html/setuser.sh' /usr/local/bin/docker-entrypoint.sh

Step: 8 – Run your containers

After following all the above steps, now you just need to run the below commands to run your containers. Get to your project folder and execute the following commands:


export UID=$(id -u $USER)

docker-compose build

docker-compose up

You can download the full code from my github docker-compose-wordpress

Related

Share this story:
  • tweet

Recent Posts

  • RaspberryPi with PiHole to block ads everywhere

    September 22, 2021 - 2 Comments
  • Reviving RaspberryPi 1 Model B in 2021 After 7 years

    September 13, 2021 - 1 Comment
  • NodeJS Consumer for AWS SQS using Docker

    November 10, 2018 - 3 Comments

Author Description

6 Responses to “WordPress development with Docker Compose”

  1. April 3, 2018

    Akkis Reply

    Thank you for this super explanatory tutorial!
    I have only one problem trying to run the very last script.
    When I write in terminal “export UID=$(id -u $USER)” then the bash answer me that UID: readonly variable.

    Any idea how to overcome this?

    • April 4, 2018

      Rajinder Deol Reply

      Hi Akkis,

      the last commands were to make the mounted wp-content folder editable via your editor, try sudo export UID=$(id -u $USER)

  2. April 3, 2018

    Akkis Reply

    Also, I checked that by removing the hack code for setuser.sh execution, everything works like a charm. I tried to upload a custom image file and it saved on the post just fine. So, maybe you should remove these lines in docker/wordpress Dockerfile.

    • April 4, 2018

      Rajinder Deol Reply

      Yes, it will work, the last step is just for the editor to edit files mounted in your docker container

  3. August 16, 2018

    Bek Reply

    Great post! Really easy to follow even for someone of my level of technical knowledge 🙂

    • October 13, 2018

      Rajinder Deol Reply

      Thanks for the appreciations Bek, I am glad you enjoyed reading the post

Leave a Reply Cancel Reply

Your email address will not be published. Required fields are marked *


*
*

Recent Posts

  • RaspberryPi with PiHole to block ads everywhere
  • Reviving RaspberryPi 1 Model B in 2021 After 7 years
  • NodeJS Consumer for AWS SQS using Docker
  • Laravel development using docker-compose with nginx and Mysql
  • Writing Your First Service in Golang Go-Micro

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 9 other subscribers

Categories

  • Android (7)
  • Education (9)
  • Go (2)
  • PHP (5)
  • Raspberry Pi (4)
  • Technology (17)
  • Web (8)

Author details:

Raj Deol

Raj Deol

Traveller, Foodie and electronics enthusiast.

View Full Profile →

© 2016. All Rights Reserved.