Categories
Web blog

Migrated to WordPress Docker container

After some deliberation, I’ve moved this site to a Docker container. My intention is to have all my web sites and services Dockerised, and sitting behind a reverse proxy server (originally Apache, but see bottom of post for NGINX config). Here are some issues I enountered and what was required to fix them.

Creating containers for the WordPress site

I have some services already running on Docker so I had that installed already. So I created a project directory where I store a docker-compose.yml file to start up my containers.

$ git clone https://github.com/martynbiz/wordpress-docker project_dir
$ cd project_dir
$ cp docker-compose.yml-example docker-compose.yml
$ cp uploads.ini-example uploads.ini

I made the neccessary changes to the docker-compose.yml and uploads.ini files, then created my containers.

$ docker-compose up -d
...
$ docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                      NAMES
9bc5f2eea5db        wordpress:5.5.0-php7.3-apache   "docker-entrypoint..."   10 seconds ago        Up 10 seconds         0.0.0.0:8001->80/tcp       martynbiz_wordpress_1
a3e222f2e684        mysql:5.7                       "docker-entrypoint..."   10 seconds ago        Up 10 seconds         3306/tcp, 33060/tcp        martynbiz_db_1

I then created and enabled a proxypass for incoming traffic on this domain to the port assigned to the container port.

Setting up the apache config ProxyPass

Debugging apache configuration isn’t my strong point as it’s not my day to day job. So far, this is working out:

<Virtualhost *:80>
    ServerName        www.martyn.biz
    ServerAlias        martyn.biz
    ProxyPreserveHost On


    <Proxy http://localhost:8001/*>
      Order deny,allow
      Allow from all
    </Proxy>

    ProxyPass         /  http://localhost:8001/ nocanon
    ProxyPassReverse  /  http://localhost:8001/


    RewriteEngine on
    RewriteCond %{SERVER_NAME} =www.martyn.biz [OR]
    RewriteCond %{SERVER_NAME} =martyn.biz
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</Virtualhost>

Error: Block mixed content

This was on the installation page so no tables had been created yet. It seems I had to add the following to the top of wp-config.php ensure assets (stylesheets, etc) were requested over HTTPS:

<?php

if ( (!empty( $_SERVER['HTTP_X_FORWARDED_HOST'])) ||      (!empty( $_SERVER['HTTP_X_FORWARDED_FOR'])) ) {     $_SERVER['HTTPS'] = 'on'; }

...

See: https://wordpress.org/support/article/faq-installation/#how-can-i-get-wordpress-working-when-im-behind-a-reverse-proxy


Anyway, next step is to move more sites to containers as well as the server software. Ideally keeping the host as bare as possible.

UPDATE

I have since installed Nginx to handle the reverse proxies. I found with other apps trying to configure them correctly in Apache to handle headers and be sent over HTTPS a bit of a pain. With Nginx, this was a breeze. Seems that Nginx definetely works better out the box for this sort of thing.

Below is my Nginx config file to do the reverse proxy for this site:

server {
    server_name martyn.biz;
    index index.html;

    location / {
        proxy_pass http://localhost:8099/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
        client_max_body_size 0;

        access_log /var/log/nginx/martynbiz.access.log;
        error_log /var/log/nginx/martynbiz.error.log;
    }

    location /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }

    location /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    listen [::]:443 ssl http2; # managed by Certbot
    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/martyn.biz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/martyn.biz/privkey.pem; # managed by Certbot
    ssl_trusted_certificate /etc/letsencrypt/live/martyn.biz/chain.pem;
}

server {
    if ($host = martyn.biz) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    listen [::]:80;

    server_name martyn.biz;
    return 404; # managed by Certbot
}

Leave a Reply

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