Running WordPress using Docker

You want to run your own instance of WordPress? Why not use Docker to containerise the deployment to make maintenance and potential host switching easy?

I have set this up – as mentioned in my first post – to run this blog.

Prerequisites

First thing you need to do is: install Docker. You will need the “community edition” (CE) to follow the examples in this post. I am not going to cover this installation as it heavily depends on your host operating system. But as it is easy to do you will figure it out following the steps on the docker website. In addition you will need to install docker-compose because it simplifies the process of defining and running docker container a lot. To make working with different containers easier I strongly recommend to install the bash command completion.

You do not need a server in the cloud to follow this post. In fact I recommend to configure and test on your local machine first. After everything works you can simply deploy to any Docker host in the cloud.

I have used a Mac book with Docker to configure and test the installation. On my cloud host I run Debian 9 (stretch) as operation system with Docker 17.12.0 and docker-compose 1.18.0 installed. All examples in this post are based on this setup.

Which components do you need?

For a standard WordPress installation you need three components.

Web server: we will use NGINX as it scales incredibly far with limited resources. Since the NGINX server is single-threaded and processes are not spawned to handle each new connection, the memory and CPU usage tends to stay relatively consistent, even at times of heavy load.

WordPress: we will use WordPress with PHP-FPM as it runs as a standalone FastCGI server and NGINX connects to the server directly. The configuration is more complex but the good news is: you do not have to deal with configuration issues as we will use a preconfigured Docker container image. You find more information about the benefits of using PHP-FPM here: https://www.cloudways.com/blog/php-fpm-on-cloud/.

How to set WordPress up?

Are you already downloading some of the archives for WordPress, NGINX and MariaDB? STOP! Because we are going to use Docker there is no need to download or install anything manually.

To make configuring docker simpler we are going to use docker-compose. To tell docker-compose which services to install and how to configure these we need to create a compose file (docker-compose.yml).

Let’s start with MariaDB

Open your editor of choice – I use nano – and create the following docker-compose.yml file:
(If you have pulled my git repository
cd DWP-examples/mariadb and have a look at docker-compose.yml.)

docker-compose.yml file for the MariaDB container

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

##############################################################

# DO NOT FORGET TO SET THE ENVIRONMENT VARIABLES IN THE FILE

# .env

# which is automatically sourced when the container are started

# we are using Compose file format version 3

version:'3'

# we want to start the following

services:

mariadb:

image:mariadb# use mariadb image

ports:

-'3306:3306'# map port 3306 of host

# to 3306 of container

volumes:

-./db-data:/var/lib/mysql# mount host directory '/db-data'

# on '/var/lib/mysql' of container

# to make db persistant

restart:always# always restart the services

# when it stops

environment:# make environment variables

# available in container

MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}

Save the file, create a file “.env”. This contains environment variables and is automatically sourced by docker-compose:

.env file for MariaDB

1

MYSQL_ROOT_PASSWORD="YourPasswordHere"

Create a directory “db-data” which will hold the db data (funny that) and type
docker-compose up into your shell. You will see the following output:

Docker downloads the necessary components for the MariaDB image, builds the image and starts the MariaDB container.

Now you have the MariaDB up and running, listening to port 3306.

Press
CTRL-c to stop the container running.

Add the WordPress container

Open the Compose file again and add the following marked lines:
( In case you want to piggy back on my GitHub repository:
cd../wordpress.)

docker-compose.yml file for WordPress and MariaDB container

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

##############################################################

# DO NOT FORGET TO SET THE ENVIRONMENT VARIABLES IN THE FILE

# .env

# which is automatically sourced when the container are started

# we are using Compose file format version 3

version:'3'

# we want to start the following

services:

mariadb:

image:mariadb# use mariadb image

ports:

-'3306:3306'# map port 3306 of host

# to 3306 of container

volumes:

-./db-data:/var/lib/mysql# mount host directory '/db-data'

# on '/var/lib/mysql' of container

# to make db persistant

restart:always# always restart the services

# when it stops

environment:# make environment variables

# available in container

MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}

wordpress:

depends_on:# WordPress depends on

-mariadb# MariaDB container running

image:wordpress:fpm# use wordpress imsge

# with fpm feature

ports:

-'9000:9000'# map port 9000 of host

# to 9000 of container

volumes:

-./wordpress:/var/www/html# wordpress content directory

# php config for larger uploads

-./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini

restart:always# always restart the service

environment:# set environment variables

WORDPRESS_DB_HOST:mariadb:3306

WORDPRESS_DB_NAME:wpdb

WORDPRESS_TABLE_PREFIX:wp_

WORDPRESS_DB_PASSWORD:${MYSQL_ROOT_PASSWORD}

Save the file. Create a directory “wordpress” where WordPress will store its php files.

To enable uploads bigger than 2 Megabyte – most WordPress themes are bigger – you need to create the following “uploads.ini” file as the default php installation will limit file uploads to 2 Megabyte. You also need to tell NGINX about the file upload limit – I will come back to this later when configuring the NGINX container.

uploads.ini file

1

2

3

4

5

file_uploads=On

memory_limit=20M

upload_max_filesize=20M

post_max_size=20M

max_execution_time=600

Type
docker-compose up into your shell. You will see the following output:

You will notice that docker starts MariaDB first and then WordPress-FPM. As both run truly non-synchronised in parallel you might see some race conditions during startup which will resolve themselves.

Looking into the directories “wordpress” and “db-data” you see the persistent files for the WordPress installation and the database. These have survived although you stopped the container.

Finish the setup with the NGINX container

Open the Compose file again (the last time I promise) and add the following marked lines:
( Using my GitHub repository:
cd../nginx.)

docker-compose.yml file for full installation

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

##############################################################

# DO NOT FORGET TO SET THE ENVIRONMENT VARIABLES IN THE FILE

# .env

# which is automatically sourced when the container are started

# we are using Compose file format version 3

version:'3'

# we want to start the following

services:

mariadb:

image:mariadb# use mariadb image

ports:

-'3306:3306'# map port 3306 of host

# to 3306 of container

volumes:

-./db-data:/var/lib/mysql# mount host directory '/db-data'

# on '/var/lib/mysql' of container

# to make db persistant

restart:always# always restart the services

# when it stops

environment:# make environment variables

# available in container

MYSQL_ROOT_PASSWORD:${MYSQL_ROOT_PASSWORD}

wordpress:

depends_on:# WordPress depends on

-mariadb# MariaDB container running

image:wordpress:fpm# use wordpress image

# with fpm feature

ports:

-'9000:9000'# map port 9000 of host

# to 9000 of container

volumes:

-./wordpress:/var/www/html# wordpress content directory

# php config for larger uploads

-./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini

restart:always# always restart the service

# when it stops

environment:# set environment variables

WORDPRESS_DB_HOST:mariadb:3306

WORDPRESS_DB_NAME:wpdb

WORDPRESS_TABLE_PREFIX:wp_

WORDPRESS_DB_PASSWORD:${MYSQL_ROOT_PASSWORD}

nginx:

depends_on:# NGINX depends on

-wordpress# WordPress container running

image:nginx:latest# use nginx image, latest release

ports:# map port WEB_PORT of host

-'${WEB_PORT}:80'# to 80 of container

volumes:

-./nginx:/etc/nginx/conf.d# NGINX config directory

-./logs/nginx:/var/log/nginx# NGINX log files

-./wordpress:/var/www/html# WordPress installation

restart:always# always restart the service

# when the service stops

Save the file. Create a directory “logs/nginx” where NGINX will store its log files.