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.
Table of Contents
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!
Hi & thanks for your guide.
What should I put in VIRTUAL_HOST if my RPi has a fixed ip and want to reach the websites inside my home network?
Hi, here you still put the URL you would like the external user to see, e.g. http://www.google.com