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.