How to set up multiple WordPress sites on Raspberry Pi with docker in 10 minutes?

In this post, I will go over how to set up multiple WordPress blogs on Raspberry Pi, using Docker and docker-compose. Our set up will use a nginx-proxy, and support https using LetsEncrypt.

Prerequisite: install docker and docker-compose on raspberry pi

In order to support multiple WordPress sites, we need a reverse proxy. The easiest way is to get a docker image going. So, we have a prerequisite.

Set up Docker and docker-compose

I am listing the steps here. The credit goes to Rohan Sawant’s post. I have tested and confirmed it works on Raspberry Pi 4 with Ubuntu server 20.04 as well.

curl -sSL https://get.docker.com | sh
sudo usermod -aG docker ubuntu

After rebooting, continue with the following steps

sudo apt-get install -y libffi-dev libssl-dev
sudo apt-get install -y python3 python3-pip
sudo apt-get remove python-configparser
sudo pip3 -v install docker-compose

Set up nginx-proxy and LetsEncrypt

Ok. Now let’s go on with setting up our reverse proxy. My plan is to use nginx-proxy and letsencrypt-nginx-proxy-companion to handle https certificates. Let’s first create a directory for the reverse proxy service:

mkdir nginx-proxy
cd nginx-proxy

The beauty of docker is we can get the image up and running. With raspberry pi though often we need to find the right image working on ARM. I created this docker-compose.yml which works well on raspberry Pi.

version: "3"
services:
  nginx-proxy:
    image: alexanderkrause/rpi-nginx-proxy
    container_name: nginx-proxy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./conf:/etc/nginx/conf.d
      - ./vhost:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - ./certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"

  letsencrypt:
    image: alexanderkrause/rpi-letsencrypt-nginx-proxy-companion
    container_name: nginx-proxy-le
    restart: always
    depends_on:
      - nginx-proxy
    volumes:
      - ./conf:/etc/nginx/conf.d
      - ./vhost:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - ./certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro

networks:
  default:
    external:
      name: nginx-proxy

A little more about nginx-proxy image

The images used here by alexanderkrause is a version adjusted based on the jwilder/nginx-proxy. A detailed post by Jason Wilder can be found here. Before using it we also need the nginx.tmpl created by jwilder.

curl -o nginx.tmpl https://raw.githubusercontent.com/jwilder/docker-gen/master/templates/nginx.tmpl

Long story short, rpi-nginx-proxy is the reverse proxy and the rpi-letsencrypt-nginx-proxy-companion will detect and automatically helps us get certificate from letsencrypt so that all the URLs we set up for each wordpress sites later will be https ready. We just have to make sure port 80 and 443 are accessible.

Create nginx-proxy network

Before starting the reverse proxy, we need to create a nginx-proxy network that we are going to use. This only has to be done once. As we will see later, our sites are going to talk to the reverse proxy via this network.

docker network create --driver bridge nginx-proxy

Let’s start the reverse proxy.

docker-compose up -d

Set up multiple WordPress blogs using docker-compose!

The next thing we are going to need is to set up our WordPress sites. Again we are going to rely on docker images so that our lives are easy. I created one directory per site.

mkdir wordpress-<sitename>
cd wordpress-<sitename>

Each site has its own directory, so that it’s easy for me to understand what’s going on. Inside each directory, I have a docker-compose.yml:

version: '3.3'

services:
   db:
     container_name: db-<sitename>
     image: hypriot/rpi-mysql
     volumes:
       - ./db_data:/var/lib/mysql
       - ./home/db:/home/db
       - ./sqldump:/sqldump
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     container_name: wordpress-<sitename>
     depends_on:
       - db
     image: wordpress:latest
     expose:
       - 80
     restart: always
     volumes:
       - ./data_volume:/var/www/html
       - ./home/wp:/home/wp
     environment:
       VIRTUAL_HOST: <YOUR_SITE_URL>
       LETSENCRYPT_HOST: <YOUR_SITE_URL>
       LETSENCRYPT_EMAIL: <YOUR_EMAIL>
       WORDPRESS_DB_HOST: db_<sitename>:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
     links:
       - db:db_<sitename>

networks:
  default:
    external:
      name: nginx-proxy

Note that for each site we are giving the container different names, and what’s the most important so that there is no conflict, note the links we set up (db:db_<sitename>). This will ensure the wordpress container always finds the correct db it should ask data from. Otherwise when you have multiple of these containers running they may mess up the linkage since we are duplicating the service names here.

Test it!

This nginx-proxy is quite powerful. For each site, nginx-proxy automatically detects they are up via the nginx-proxy network we set up. Then letsencrypt companion will look at the host name and email we configure for each site, and pulls the certificate for us. It takes a little bit time for the site to become up and running since the letsencrypt companion needs to do this work first.

Finally we start the instance for each site. In each directory of the sites, execute:

docker-compose up -d

Voila! You should now be able to access the sites with the https://<your_site_url> address for all of them. We have accomplished the task to set up multiple WordPress sites on Raspberry Pi!

2 comments

Leave a ReplyCancel reply