Benefits of WordPress + Docker in a production environment + troubleshooting guide.

Even though we are a Rails development team, we use WordPress for our blog. We love Rails, but WordPress provides a robust solution for our blogging needs. And lately, we have been experimenting with Docker + WordPress.

So, why Docker?

There are quite a few straightforward reasons why we use Docker with WordPress, namely:

Docker reduces clutter.

We can run a couple of Rails applications and WordPress instances on the same server.

It helps with version conflict management in Rails apps

It allows for the duplication of a production server into staging for testing purposes.

We can “dockerize” an application, run it in our laptops, run tests and then deploy with confidence that it will work. If you are new to Docker, you should read What is Docker and Dockerizing applications. So, the plan is to apply this process to our application. However, I found some issues while building the instances. I would like to share those issues and how I managed to solve them.

Creating a WordPress instance

Try a simple search. I first tried this instance but didn’t like the lack of documentation, and that I wasn’t able to save the uploaded files in a persistent volume. Then I tried this other one but wasn’t able to modify wp-config.php without some hacking. So, I built my own WordPress image instead.

Dockerfile

This file is responsible for creating the docker instance. You can check the Dockerfile instance here. Let me explain each line, so that it all makes sense.

1

FROM framallo/php-fpm

I created a base image php-fpm that allows you to run any PHP application. It is based on ubuntu:14.04.

1

2

3

4

5

6

7

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update

RUN apt-get install-ycurl mysql-client

RUN rm-rf/var/lib/apt/lists/*

The first line is to avoid mysql to ask for a root user and password. Then I updated the apt-cache and install curl and mysql client. Last, I removed the apt-cache to reduce the instance size.

This actually installs WordPress. It’s designed to be in one line so that Docker can cache it completely

1

RUN cp-r/var/wordpress/*/var/www

Then I copy WordPress to the correct folder.

1

ADD wp-config.template.php/var/www/wp-config.template.php

I copy a template to generate wp-config.php. When the instance starts I run the 40_parse_wordpress_config.sh init script. I use bash to render the template using ENV variables. For instance, ${DB_NAME} will be converted to *wordpress_development*. I found the template parser script here.

The issue is that PHP doesn’t inherit the environment variables, so I had to modify wp-config.php in order to set all the variables that the application needs.

1

2

3

RUN chown-Rwww-data:www-data/var/www

RUN chmod755-R/var/www/

I prepare the files to be accessible by nginx and PHP

1

VOLUME/var/www

This line allows you to create persistent storage for the uploaded files and other application changes.

1

2

3

ADD *.sh/

RUN chmod+x/*.sh

These lines prepare the init scripts. I add them and set as executable scripts.

1

CMD forfin/*.sh;do$f;done

When the instance starts it will run each init script. The last one is 50_init.sh from php-fpm which runs nginx and php-fpm. All the previous scripts should execute and stop to allow the init process to work.

The “build” attribute is the Dockerfile folder. “Links” allows you to connect it with mysql. “Ports” refers to the exposed ports. The format is <host port>:<instance port>. “Environment” allows you to setup the instance

1

2

3

4

5

6

7

db:

image:mariadb

environment:

MYSQL_ROOT_PASSWORD:12345Abc

This is to run the database. The password in MYSQL_ROOT_PASSWORD should be the same as DB_PASS

Creating a data volume

In order to run it in production, you need to save the uploaded files. You can use a data volume for that.

In docker-compose.yml you need to add the following:

1

2

3

volumes_from:

-wordpressdata

And add another image to docker-compose.yml:

1

2

3

4

5

6

7

8

9

wordpressdata:

image:framallo/wordpress

volumes:

-/var/www

command:echo'wordpress data initialized'

So every file that is uploaded or modified will be saved in the wordpressdata image.

Just be careful when you are cleaning up docker and removing old images because you could delete wordpressdata.

Another nginx instance.

If you run the example docker-compose.yml it will work. However, WordPress will be connected to port 80 and we won’t be able to run another instance. We need to add another nginx to act as a reverse proxy.

I added the following lines to docker-compose.yml:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

proxy:

image:framallo/nginx

links:

-wordpress

ports:

-80:80

volumes:

-sites:/etc/nginx/sites-template

environment:

VERBOSE_TEMPLATES:true

And removed the ports attribute in WordPress. Now the proxy connects to WordPress using the env variables and can expose multiple applications.

Here’s where we end for now. In conclusion, after having solved the minor issues mentioned above, we found Docker to be a very useful and efficient tool to manage distributed applications. Give it it a try when you can. Let me know if you have any questions about how our instance works, or check out our documentation here.