Containerize WordPress and Make It Work With HAProxy

After running for 4 years on a VM, this WordPress blog was migrated to a Docker container yesterday. It was not as smooth as expected because of database, file structure, and load balancer/HTTPS issues. Here are the challenges I got and how I fixed them.

At first I followed this tutorial [link] to move database and static files. But the old server runs PHP 5.4 and MySQL 5.1 which needed immediate upgrade. MySQL 5.7 upgrade was tricky, as mysqld had to be up for mysql_upgrade to fix old database and it turns out to be a catch-22. The fix [link] was to skip grant tables to run mysqld first and upgrade db.

All the db migration turned out to be unnecessary, because there is an All-in-One Migration tool just for that [link]. So here begins my what I really did:

  1. Back up your WordPress with this tool [link].
  2. Set up new container with Docker-compose. You need to forward 80:80 for the first time of setting up WordPress.
  3. Set up a new blog on port 80.
  4. Set up HAProxy.
  5. Update wp-config.php, if your back up file is big, update .htaccess too.
  6. Install All-in-One Migration [link] and restore your back up.
# haproxy.cfg
   tune.ssl.default-dh-param 1024
   log local0
   option tcplog
   timeout connect 5000ms
   timeout client 50000ms
   timeout server 50000ms
 frontend http_gateway
   mode http
   bind :80
   redirect scheme https if !{ ssl_fc }
 frontend secure_gateway
   mode http
   bind ssl crt your-cert-file.pem 
   http-request set-header X-Forwarded-Proto https if { ssl_fc }
   # content switching based on SNI
   use_backend bk_cert1 if { ssl_fc_sni }
 backend bk_cert1
   mode http
   server srv1 your-container-ip:80
# Add to .htaccess
php_value upload_max_filesize 64M
php_value post_max_size 128M
php_value memory_limit 256M
php_value max_execution_time 300
php_value max_input_time 300
# Add to wp-config.php
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
   $_SERVER['HTTPS'] = 'on';
   $_SERVER['SERVER_PORT'] = 443;

Note: X-Forwarded-Proto is required for WordPress to recognize it’s in an HTTPS environment.

Published on February 4, 2019