This blog was running on WordPress on a dedicated Ubuntu 14.04 VM host. When I tried to update the host to Ubuntu 16.04, I broke WordPress. Rather than trying to figure out what went wrong, I decided to just run a new WordPress instance under Docker and move the blog to that.
The transition wasn’t quite as easy as I’d hoped, so here are the steps (and missteps) I followed to finally get it to work.
I first created a directory “blog” and two subdirectories “wp-content” and “db” on a docker host (an Ubuntu 16.04 VM) and brought up a new instance of the WordPress image from the official Docker repository (https://hub.docker.com/_/wordpress/) with the following docker-compose.yml file:
version: '3.1'
services:
wordpress:
image: wordpress
container_name: blog_wordpress
restart: always
ports:
- 5004:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: administrator
WORDPRESS_DB_PASSWORD: '*****'
WORDPRESS_DB_NAME: blog
volumes:
- ./wp-content:/var/www/html/wp-content
db:
image: mysql:5.7
container_name: blog_db
restart: always
environment:
MYSQL_DATABASE: blog
MYSQL_USER: administrator
MYSQL_PASSWORD: '*****'
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- ./db:/var/lib/mysql
I brought it up (docker-compose up -d), checked the logs (docker-compose logs -f). It looked OK, so pointed my browser at http://d1:5004 (where d1 is the name of the Docker host I brought it up on).
The WordPress installation appeared:
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/image-1024x588.png)
and I went through the installation screen:
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.08.00-1024x987.png)
I was then able to login at http://d1:5004:
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.10.41-1024x707.png)
So far, so good! Now I had to figure out how to move over the content from the old blog to the new one. After reading reviews and trying out a few alternatives, I settled on the “All-in-one WP Migration” plug-in which I first installed in the old blog and exported the contents to a file which I downloaded. Now to upload it to the new blog. I tried to install the plug-in in the new blog and ran into the first problem – the plugin installation said WordPress had no write access to the directory where it wanted to install.
After reading around a bit, I found the following solution:
$ docker exec -it blog_wordpress /bin/bash
$ chown www-data:www-data -R *
Note: this problem only occurred on a Linux Docker host – on a mac, I was able to install plugins without this step.
I then installed the plug-in successfully in the new blog and started the upload:
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.16.23-1024x547.png)
Here I ran into the second problem – the upload limit was 2MB and the migration file was 120MB. The plugin suggested inserting a few lines into the .htaccess file to solve the problem:
$ docker exec -it blog_wordpress /bin/bash
$ nano .htaccess
# insert the following lines
php_value upload_max_filesize 128M
php_value post_max_size 128M
php_value memory_limit 256M
php_value max_execution_time 300
php_value max_input_time 300
Of course, being a Docker container, there’s no nano editor (or even vi), so you’ve got to first do a “apt update” and a “apt install nano”. After refreshing the screen, the limit had increased to 128MB and I imported the migration file.
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.28.30-1024x1009.png)
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.30.38-1024x897.png)
Logging in to the administration screen at at http://d1:5004/wp-admin, it looked like everything had been migrated successfully
![](https://blog.armstrongconsulting.com/wp-content/uploads/2019/06/Screenshot-2019-06-06-at-11.32.40-1024x736.png)
Now to get the new site published via our proxy. We’re using HAProxy with SSL termination with LetsEncrypt certs, so I’d need rules to map https://blog.armstrongconsulting.com to http://d1:5004.
backend blog
server d1 d1:5004
frontend main
acl host_blog hdr(host) -i blog.armstrongconsulting.com
use_backend blog if host_blog
I then pointed my browser at blog.armstrongconsulting.com and was dismayed to see that I was redirected to https://blog.armstrongconsulting.com:5004. Ouch! Looks like WordPress somehow remembers the port you installed it at and redirects the browser to it.
I tried to use a Search & Replace plugin to find references to d1:5004 and replace it with blog.armstrongconsulting.com, but I couldn’t get it to work. In the end I gave in and repeated the installation from scratch, but this time with the proxy rules already in place and I repeated the installation using the URL https://blog.armstrongconsulting.com.
My troubles weren’t over though. I immediately ran into another problem. WordPress depends on the “X-Forwarded-Proto” header (set to “https”) to know that its behind a reverse-proxy server which is doing SSL termination (i.e. https into the proxy, but http to the backend). I had to update our HAProxy frontend configuration to add the header to let WordPress know to use https references :
http-request set-header X-Forwarded-Proto https if { ssl_fc }
Finally, everything worked. However, the whole experience was much more of a challenge than I would have hoped for. Its a pity that WordPress is such a hassle to install on a different port behind a reverse proxy.
I assume that if you’re a WordPress expert, you’d know how to update the URL correctly in WordPress’s database, but I tried several times and each time ended up with a completely broken installation.