Dockerizing wordpress

March 18, 2018

Introduction

In the INOWAS-project we are using a wordpress as CMS for a Wiki-page, which grew in the last year a lot.
The backup of the website is now about 180Mb, with a database of about 20Mb.

As we have to move to another server, my idea was to move the project to a docker-stack before moving it to the new hardware.

Structure

Nginx is used as a proxy-server for the different projects on the server.

Settings

The Old System

  • Source-Folder: /var/www/wiki
  • Database: MySQL Database on the debian-host

The dockerized System

  • The project folder: /srv/docker/wiki
  • The docker-compose folder: /srv/docker/wiki/docker
  • The source-folder: /srv/docker/wiki/source
  • The upstream-port on the host-system: 8010

Moving the wordpress to docker

Create a wordpress multi-container-application

Docker Compose is a tool for defining and running multi-container Docker applications.

Create a docker-compose.yml file with the following content:

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - dbdata:/var/lib/mysql
       ${DATABASE_IMPORT_FOLDER}:/db
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
       MYSQL_DATABASE:      ${MYSQL_DATABASE}
       MYSQL_USER:          ${MYSQL_MYSQL_USER}
       MYSQL_PASSWORD:      ${MYSQL_PASSWORD}

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - ${HTTP_PORT}:80
     restart: always
     volumes:
      - ${WORDPRESS_FOLDER}:/var/www/html
     environment:
       WORDPRESS_DB_HOST:     db:3306
       WORDPRESS_DB_NAME:     ${MYSQL_DATABASE}
       WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
       WORDPRESS_DB_USER:     ${MYSQL_MYSQL_USER}
       WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
    dbdata:
      driver: "local" 

All $-signed variables can be specified in a .env file. Create a .env-file with the following content:

COMPOSE_PROJECT_NAME=wiki
HTTP_PORT=8010
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=wordpress_db
MYSQL_USER=wordpress_user
MYSQL_PASSWORD=wordpress_password
SOURCE_FOLDER=../source
DATABASE_IMPORT_FOLDER=../db_import

Run the application in daemon-mode:

$ docker-compose up -d

After downloading the images, the container should run after a while.

With ‘docker-compose ps’ you can check if the containers are running properly

$ docker-compose ps
      Name                    Command               State          Ports
--------------------------------------------------------------------------------
wiki_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp
wiki_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8010->80/tcp

With ‘docker-compose logs’ you can check what’s happening in the containers.

Migrating the Source-files and setting the file permissions

$ cp -r /var/www/wiki /srv/docker/wiki/source

Here you can find this ready-to-run script to fix the permissions.

#!/bin/bash
#
# This script configures WordPress file permissions based on recommendations
# from http://codex.wordpress.org/Hardening_WordPress#File_permissions
#
# Author: Michael Conigliaro <mike [at] conigliaro [dot] org>
#
WP_OWNER=www-data # <-- wordpress owner
WP_GROUP=www-data # <-- wordpress group
WP_ROOT=$1 # <-- wordpress root directory
WS_GROUP=www-data # <-- webserver group

# reset to safe defaults
find ${WP_ROOT} -exec chown ${WP_OWNER}:${WP_GROUP} {} \;
find ${WP_ROOT} -type d -exec chmod 755 {} \;
find ${WP_ROOT} -type f -exec chmod 644 {} \;

# allow wordpress to manage wp-config.php (but prevent world access)
chgrp ${WS_GROUP} ${WP_ROOT}/wp-config.php
chmod 660 ${WP_ROOT}/wp-config.php

# allow wordpress to manage wp-content
find ${WP_ROOT}/wp-content -exec chgrp ${WS_GROUP} {} \;
find ${WP_ROOT}/wp-content -type d -exec chmod 775 {} \;
find ${WP_ROOT}/wp-content -type f -exec chmod 664 {} \;

Migrating the database

Export the current database

As we had some issues with http and https-urls I have uses the Migrate DB-Plugin to export the database with some regex-stuff.
Another option is to export the database with a mysqldump:

$ mysqldump -u username --password=password database > /srv/docker/wiki/db_export.sql

Once exported, the database can be imported into the dockerized system:

$ cd /srv/docker/wiki/docker
$ docker-compose exec db bash
$ mysql -u wordpress_user --password=wordpress_password wordpress_db < /db/db_export.sql

Configure the host-nginx

server {
    listen  80;

    server_name wiki.inowas.hydro.tu-dresden.de
    return 301 https://$host$request_uri;
}

server {
    listen  443;

    server_name wiki.inowas.hydro.tu-dresden.de;

    ssl on;
    ssl_certificate /etc/nginx/ssl/bundle.crt;
    ssl_certificate_key /etc/nginx/ssl/key-decrypted.pem;

    location / {
        proxy_set_header    X-Real-IP  $remote_addr;
        proxy_set_header    X-Forwarded-For $remote_addr;
        proxy_set_header    Host $host;
        proxy_set_header    X-Forwarded-Proto $scheme;
        proxy_pass          http://127.0.0.1:8010;
    }

    error_log /var/log/nginx/wiki_error.log;
    access_log /var/log/nginx/wiki_access.log;
}

Changing the wp-config

I you are running your website with ssl on port 445 (https) you should add the following lines to the wp-config.php. This prevents possible “too many redirects” errors.

/**
 * For WordPress, force the protocol scheme to be HTTPS
 * when is_ssl() doesn't work, e.g. on a reverse proxied server
 * where _SERVER['HTTPS'] and _SERVER['SERVER_PORT'] don't
 * indicate that SSL is being used.
 */
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
    $_SERVER['HTTPS'] = '1';

if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}

Summary

This guide shows you how to migrate your old wordpress to a containerized docker-application.

With creating a new nginx-config and a wordpress-container this should be an easy job.

You can export your existing dababase easily and copy your source-folder to the new location. You have to adapt the file permissions and tweak your wp-config a bit that it works.

Have fun with your new system.


comments powered by Disqus