Dockerize a WordPress instance

Yeah, I know, its been a while since I’ve posted anything. Been busy and stuff. But that doesn’t mean I’ve been lazy and didn’t do shit : I tried to learn more about Docker and Devops in general.

So recently, I decided to switch my “old” LAMP instance to a new LEMP stack. Byebye Apache, MYSQL and PHP5 and welcome NGINX, MariaDB and PHP7!

Here is a short description of what I wanted :

  • A NGINX container that I could easily configure
  • A MariaDB instance
  • And of course the lastest version available of PHP

I didn’t want a single WordPress Container because I will probably add more services to this server, like a chat or something.

To dockerize an already existing WordPress blog, we will do the following :

  1. Backup the old database and upload our wordpress archive to the new server.
  2. Create the necessary config file for NGINX and a docker-compose.yml to easily configure and start our containers.
  3. Set up the firewall.
  4. Import our old database.
  5. Demonize our docker-compose

To backup a MySQL database, just do this :

$ mysqldump -u root -p YOUR_WORDPRESS_DATABASE > backup.sql

Create an archive of your wordpress folder and upload the whole thing to your new server :

$ scp backup.sql YOUR_USER@YOUR_SERVER:.
$ cd /var/www/
$ tar -cvf wordpress.tar /wordpress 
$ scp wordpress.tar YOUR_USER@YOUR_SERVER:.

On your new server, create a bunch of new directories in /opt/ :

$ mkdir -p /opt/nginx/conf.d
$ mkdir /opt/mariadb

We will now use docker-compose to define and run our multi-container Docker applications :

$ vim /opt/docker-compose.yml
version: "2"
services:
nginx:
image: tutum/nginx:latest
ports:
- 80:8080
- 443:8443
volumes:
- /opt/nginx/conf.d/wordpress.conf:/etc/nginx/sites-enabled/default
- /opt/nginx/conf.d/wordpress.conf:/etc/nginx/sites-available/default
- /etc/ssl:/etc/ssl
- /var/log/nginx/error.log:/var/log/nginx/error.log
- /var/log/nginx/access.log:/var/log/nginx/access.log
- /var/www/wordpress:/var/www/wordpress
links:
- mariadb
- php
mariadb:
image: mariadb:latest
ports:
- 3306:3306
environment:
MYSQL_DATABASE: "YOUR_BLOG_DATABASE_NAME"
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_USER: "YOUR_BLOG_USERNAME"
MYSQL_PASSWORD: "YOUR_DATABASE_PASSWORD"
volumes:
- /opt/mariadb:/docker-entrypoint-initdb.d
- /opt/mariadb:/var/lib/mysql
php:
# i just prefer this image cause it contains the necessary php extensions
image: m0zziter/php7-fpm-wordpress
ports:
- 9000:9000
volumes:
- /var/www/wordpress:/var/www/wordpress

Create and open a file on /opt/nginx/conf.d/wordpress.conf, paste the following and adapt it to your needs :

server {
listen      *:8080 default;
listen      [::]:8080;
server_name YOUR_SERVER.NAME;
## redirect http to https ##
rewrite     ^ https://$server_name$request_uri? permanent;
}
server {
# listens both on IPv4 and IPv6 on 443 and enables HTTPS and HTTP/2 support.
# HTTP/2 is available in nginx 1.9.5 and above.
listen *:8443 ssl;
listen [::]:8443 ssl;
# indicate locations of SSL key files.
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
## Your website name goes here.
server_name YOUR_SERVER.NAME;
## Your wordpress path reference.
root /var/www/wordpress;
## This should be in your http block and if it is, it's not needed here.
index index.php;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string          
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# php : adapt it to your container name and port
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
# Set caches, protocols, and accepted ciphers. This config will merit an A+ SSL Labs score as of Sept 2015.
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5';
}

Now, decompress your wordpress archive to a folder like /var/www/ :

$ tar -xvf wordpress.tar -C /var/www

And copy your backup script to /opt/mariadb

$ cp backup.sql /opt/mariadb/.

Now let’s create the appropriate firewall rules. In my situation, I prefer FirewallD and I’m sure you won’t have any problem doing the same with iptables :

# firewall-cmd --add-service=http --permanent
# firewall-cmd --add-service=https --permanent
# firewall-cmd --reload

But before starting the whole thing, we should be sure to add our current user to the Docker group and create a new docker user :

# adduser USERNAME docker
# useradd docker

And replace the “/bin/bash” in the end of /etc/passwd by “/usr/sbin/nologin”

And now we can finally start the whole thing :

$ cd /opt/
$ docker-compose up

You can interrupt the process after you see a line that confirms that your previous database was imported and that NGINX and PHP7 are both up and running.

No we can finally create the systemd file to automatically start our containers :

# vim /etc/systemd/system/wordpress.service
[Unit]
Description=wordpress service : start nginx and mariadb
Requires=docker.service
After=docker.service
[Service]
Restart=always
WorkingDirectory=/opt/
ExecStart=/usr/local/bin/docker-compose up
ExecStop=/usr/local/bin/docker-compose down
User=docker
Group=docker
[Install]
WantedBy=default.targe

And of course :

# systemctl daemon-reload
# systemctl enable wordpress.service
# systemctl start wordpress.service

If you encounter any problem, please check your error.log file that we set and be sure to have properly set the correct variables in your wp-config.php file.

Leave a Reply

Your email address will not be published. Required fields are marked *