Dockerizing Wordpress with Nginx and PHP-FPM on Ubuntu 16.04

Docker-Compose is a command line tool for defining and managing multi-container docker containers as if they were a single service. Compose is written in python and can be installed with the Python pip command. With compose, we can run multiple docker containers just with a single command. It allows you to create a container as a service, great for your development, testing and staging environment.

In this tutorial, I will guide you step-by-step to use docker-compose. We will deploy 'Wordpress' with Nginx, MySQL, and PHP-FPM. Each service has its own container, and we will use images from the docker hub registry. I will show you how to create containers from docker images and manage all containers with docker-compose.

Prerequisite

  • Ubuntu 16.04
  • Root Privileges

Step 1 - Install Docker

We will start from scratch, by installing docker and docker compose manually with the apt command.

Before we begin, update the Ubuntu repository and install latest updates:

sudo apt-get update
sudo apt-get upgrade

By default, docker is available in the Ubuntu repository, so we can continue to install it right away:

sudo apt-get install -y docker.io

When the installation is done, start docker and add it to start automatically at boot time:

systemctl start docker
systemctl enable docker

Now test your docker installation with the command below:

docker run hello-world

You will see hello-world from docker.

Step 2 - Install Docker-Compose

Docker-compose is a script written in python, it's available in the PyPI python repository and can be installed with python pip. So we need to install python and python pip on our system first.

Install python and python-pip:

sudo apt-get install -y python python-pip

Next, install docker-compose with the pip command:

pip install docker-compose

wait for the installation process to finish. Then check the installation with the docker-compose command:

docker-compose -v

You will get the docker-compose version.

Step 3 - Setup Wordpress

Now, docker and docker-compose are installed on the system. In this step, will show you how to create and setup the docker-compose environment for our WordPress project.

We will deploy the 'Wordpress' PHP application with Nginx as the web server, and MariaDB for the MySQL database as docker containers managed by docker-compose. Each application (Wordpress, Nginx, and MySQL) will run in its own container, you can see the list below:

- Nginx: We use the official docker image, latest version 'nginx: latest'.

- Wordpress: Wordpress provides some docker images on docker-hub, and we will use WordPress 4.7 with PHP-FPM 7.0 on it.

- MySQL: We will use MariaDB official container, latest version.

So we need 3 docker images from the docker hub registry.

We will not run docker as root, we will use normal Linux user. So just create a new user with command below (feel free to use a different username here, just ensure the user does not exist yet. If you choose a different name, ensure to change it in all commands that follow in this tutorial):

useradd -m -s /bin/bash hakase
passwd hakase

Now add the user to the 'docker' group so the user can use the docker command, and restart the docker service:

usermod -a -G docker hakase
systemctl restart docker

Login to the user 'hakase' and create a new directory for the WordPress project:

su - hakase
mkdir -p wordpress-compose
cd wordpress-compose/

Next, create a new file called 'docker-compose.yml', and create a new directory for the project. Just type the commands below:

touch docker-compose.yml
mkdir -p nginx/
mkdir -p db-data/
mkdir -p logs/nginx/
mkdir -p wordpress/

File and Directory List of the project:

- docker-compose.yml: This is the docker-compose configuration file, you must create it when starting new docker-compose project.

- nginx/: This directory is used for our additional nginx configuration like the virtual host etc.

- db-data/: The volume/directory for the mysql data. The sql from data '/var/lib/mysql' is mounted to db-data directory.

- logs/: Directory for application log, nginx, mariadb and php-fpm.

- wordpress/: All wordpress files will be available in that directory.

In the 'nginx' directory, create a new configuration file for our wordpress virtual host.

Create a new file wordpress.conf:

vim nginx/wordpress.conf

Paste configuration below:

server {
    listen 80;
    server_name wp-hakase.co;

    root /var/www/html;
    index index.php;

    access_log /var/log/nginx/hakase-access.log;
    error_log /var/log/nginx/hakase-error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass wordpress:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

Save the file and exit vim.

Step 4 - Configure Docker-Compose

In this step, we will start editing the docker-compose.yml file. When you want to start the docker-compose project, make sure you create the docker-compose.yml file first like we do it below.

Edit docker-compose.yml with vim:

vim docker-compose.yml

Define your services, on the first line we will define Nginx. We are using Nginx official docker image, the latest version, and configure port mapping for port 80 on the container to port 80 on the host. Next, configure the docker volumes, the volume for our Nginx virtual host configuration, volume for Nginx log files and the web root directory volume '/var/www/html'. The Nginx container is linked to WordPress container.

Paste configuration below:

nginx:
    image: nginx:latest
    ports:
        - '80:80'
    volumes:
        - ./nginx:/etc/nginx/conf.d
        - ./logs/nginx:/var/log/nginx
        - ./wordpress:/var/www/html
    links:
        - wordpress
    restart: always

Next, define the MySQL server. We are using the MariaDB image, latest version. Configure port mapping for the container on port 3306, and configure the MySQL root password with the environment variable 'MYSQL_ROOT_PASSWORD'. Finally, configure the container volume for the MySQL data directory.

Paste configuration below:

mysql:
    image: mariadb
    ports:
        - '3306:3306'
    volumes:
        - ./db-data:/var/lib/mysql
    environment:
        - MYSQL_ROOT_PASSWORD=aqwe123
    restart: always

Then we will configure the WordPress service by using the WordPress 4.7 docker image with PHP-FPM 7.0 installed. Configure the port for PHP-fpm on port 9000, enable the docker volume for the web directory '/var/www/html' to the host directory 'wordpress', setup the database by defining WordPress environment variable, and link the WordPress service to mysql.

Paste configuration below:

wordpress:
    image: wordpress:4.7.1-php7.0-fpm
    ports:
        - '9000:9000'
    volumes:
        - ./wordpress:/var/www/html
    environment:
        - WORDPRESS_DB_NAME=wpdb
        - WORDPRESS_TABLE_PREFIX=wp_
        - WORDPRESS_DB_HOST=mysql
        - WORDPRESS_DB_PASSWORD=aqwe123
    links:
        - mysql
    restart: always

After adding the three parts into the docker-compose.yml file, save the file and exit the vim editor.

Our docker-compose configuration is ready.

Step 5 - Run Docker-compose

Start to create the new containers with docker compose. Go to the wordpress-compose directory and start the new containers based on our compose file.

cd ~/wordpress-compose/
docker-compose up -d

You can see the results of the command. Three containers were created. Let's check the container status with the ps option:

docker-compose ps

Below is the result:

Start Docker-compose Wordpress

If you want to see the log output from the container, you can use commands below:

docker-compose logs nginx
docker-compose logs mysql
docker-compose logs wordpress

Container logs:

an example for docker-compose logs command

Note:
If you see in the WordPress container log an error about MySQL connection refused, ignore it.

Step 6 - Install Wordpress

Before we do this step, let's check the available ports/open ports on the system. Make sure you have 3 ports opened, port 80, 3306 and port 9000.

netstat -plntu

The results are below:

Port open docker

Now open your web browser and type in the server URL or IP address.

http://serverIP/

You can see the WordPress installation page. Choose your language and click 'Continue'.

Wordpress Installation set languange

Fill in your website details like site title, admin user and password, your email address and then click 'Install Wordpress'.

Install Wordpress Fill User and Site Configuration

You will be redirected to the 'Wordpress Admin Dashboard'.

Wordpress Admin Dashboard Docker-Compose

And this is my WordPress sample post hello world.

Wordpress woth Docker-Compose

Wordpress has been installed with docker-compose.

Step 7 - Accessing the Docker Container

This is an additional step on how to access a container with docker-compose. Check that all containers are available and show their status:

docker-compose ps

We already have 3 containers, now we can try to login to each container. Log in to the first Nginx container with docker-compose command.

docker-compose exec nginx bash

nginx: service name on the docker-compose file docker-compose.yml

bash: execute the bash shell command

Now check our WordPress virtual host configuration.

cat /etc/nginx/conf.d/wordpress.conf

Nginx docker compose service

The files are available in the container.

Next, try login to the mysql container, and then log into the mysql shell with our password on the compose file.

docker-compose exec mysql bash
mysql -u root -p
TYPE MYSQL ROOT PASSWORD

See the list of databases:

show databases;

You will see our WordPress database.

MySQL Docker Compose service

In the 'wordpress' container, you will see all WordPress files.

docker-compose exec wordpress bash
ls -lah

Wordpress with PHP-FPM Docker Compose

All containers are accessible.

Reference

Share this page:

Suggested articles

7 Comment(s)

Add comment

Comments

From: TiTex at: 2017-04-06 11:32:44

docker.io package is alwasy outdated , you should check this page to install latest docker https://docs.docker.com/engine/installation/linux/ubuntu/

usermod -a -G hakase dockershould be usermod -a -G  docker hakase

 

 

Next, create new file called 'docker-container.yml', and create a new directory for the project. Just type the commands below:should beNext, create new file called 'docker-compose.yml', and create a new directory for the project. Just type the commands below:

 

you do not need to expose ports on the host for mariadb and php-fpm , if you don't want to do anything with them

    ports:        - '9000:9000'     ports:        - '3306:3306

From: nam at: 2017-04-06 11:45:54

some small mistake in command when add user to docker group

"usermod -a -G hakase docker" 

usermod -a -G docker hakase

From: till at: 2017-04-06 12:54:49

Thank you @TiTex and @nam. I've corrected the tutorial.

From: David Dumonde at: 2017-04-06 15:22:07

I haven't been able to create more than one wordpress site on a single host using docker-compose. Any suggestions for creating multiple wp containers with this setup?

From: TiTex at: 2017-04-07 15:30:36

you need to change each nginx container's ports to something unique like

    ports:        - '8080:80'

    ports:        - '8081:80'

From: David Dumonde at: 2017-04-08 01:28:00

Thanks, @TiTex, that works in a sense, but it will leave the url exposed as example.com:8080 or example.com:8081. Without docker, I can set up nginx server blocks for each domain so that they listen :80, and then are separated by their root, such as root /var/www/html/site1 or root /var/www/html/site2 without needing separate ports. So I don't think the port settings are the answer I'm looking for, but I appreciate your help.Right now I'm looking at how to change the location block setting for different sites to fastcgi_pass site1:9001 or fastcgi_pass site2:9002. I got it to work with two sites, then when I added a third site I started getting 502 bad gateway errors. I'm still tinkering.

From: ofthesun9 at: 2017-04-13 11:31:01

Thanks for this clear & simple howto !

What would be the changes required to have wordpress install in "mysite.com/blog" instead of mysite.com ?