Running multiple WordPress instances on the same docker server

With the following “Docker recipe”, you will set up a Docker node running separate WordPress installation on two domains or subdomains. This setup is pretty much production ready, with:

  • nginx reverse proxy by Jason Wilder that automatically routes traffic to new containers that are created with the environment variable.  This nifty container performs a similar function to Traefik or HAProxy, but it is amazingly simple to use.
  • letsencrypt-nginx-proxy-companion by Yves Blusseau that obtains an SSL certificate from Let’s Encrypt, the free Certificate Authority, when you specify the LETSENCRYPT_HOST and LETS_ENCRYPT_EMAIL environment variables on any application container (i.e. WordPress) that needs to be served over HTTPS. The companion even pings Let’s Encrypt every 90 days to automatically renew your certificates!
  • Official MariaDB and WordPress containers from the docker-library, approved by the Docker Store.

Many thanks to the maintainers of these containers, who have open sourced the Dockerfiles on GitHub and are well reputed in the community. The only things you really need to change for the recipe below to be ready to go are the parameters highlighted in blue.

Create DNS Records 

From your DNS provider, which may be your domain registrar or a third-party service such as CloudFlare, create A records for the domains and/or subdomains where you want to install WordPress, towards the outward facing IP address of your Docker host. Use a short time to live (TTL), such as 3,600 seconds or less to reduce the time that the DNS records will take to propagate.

Install Docker

Find out how to set up your Docker environment on Linux here. You need SSH access to your server, which should run Ubuntu, Debian, Fedora or CentOS in order to use the community edition of Docker. If your VPS provider, such as DigitalOcean provides a “one click install”, it’s okay to use that as well.

Create swapfile

Create a swap file to prevent your MariaDB or WordPress containers from running out of memory under load.

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Create non-root user account for Docker (recommended)

You can execute docker commands as root, but it’s recommended to create a normal user account and add that user to the docker group. For security reasons, you shouldn’t generally be performing tasks on your Linux box as root. Instead, add a regular user account to the sudo (Ubuntu) or wheel (CentOS) group so you can execute commands as sudo.

sudo useradd dockeruser
sudo usermod -aG docker dockeruser
sudo usermod -aG sudo dockeruser
login dockeruser

Run the Nginx-Proxy, MariaDB, WordPress containers

1. First, create a Docker network. This enables container DNS, which allows containers to communicate with one another by name.

docker network create dockerwp

2. Start the Nginx proxy.

docker run --name nginx-proxy --net dockerwp -p 80:80 -p 443:443 -v ~/certs:/etc/nginx/certs -v /etc/nginx/vhost.d -v /usr/share/nginx/html -v /var/run/docker.sock:/tmp/docker.sock:ro --label com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy -d --restart always jwilder/nginx-proxy

3. Start the Let’s Encrypt Nginx Proxy Companion.

docker run --name letsencrypt-nginx-proxy-companion --net dockerwp -v ~/certs:/etc/nginx/certs:rw -v /var/run/docker.sock:/var/run/docker.sock:ro --volumes-from nginx-proxy -d --restart always jrcs/letsencrypt-nginx-proxy-companion

4. Start the MariaDB containers.

docker run --name mariadb1 --net dockerwp -v mariadb1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=supersecret -e MYSQL_DATABASE=db1 -e MYSQL_USER=db1user -e MYSQL_PASSWORD=secret -d --restart always mariadb
docker run --name mariadb2 --net dockerwp -v mariadb2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=supersecret -e MYSQL_DATABASE=db2 -e MYSQL_USER=db2user -e MYSQL_PASSWORD=secret -d --restart always mariadb

5. Enable large file uploads in WordPress (> 2 MB).

printf "file_uploads = On\nmemory_limit = 64M\nupload_max_filesize = 64M\npost_max_size = 64M\nmax_execution_time = 600" > ~/uploads.ini

6. Start the WordPress containers.

docker run --name wordpress1 --net dockerwp -v wordpress1:/var/www/html -v ~/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini -e WORDPRESS_DB_HOST=mariadb1:3306 -e WORDPRESS_DB_NAME=db1 -e WORDPRESS_DB_USER=db1user -e WORDPRESS_DB_PASSWORD=secret -e -e -e -d --restart always wordpress
docker run --name wordpress2 --net dockerwp -v wordpress2:/var/www/html -v ~/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini -e WORDPRESS_DB_HOST=mariadb2:3306 -e WORDPRESS_DB_NAME=db2 -e WORDPRESS_DB_USER=db2user -e WORDPRESS_DB_PASSWORD=secret -e -e -e -d --restart always wordpress
Explore More

Now that you have two secure, containerized WordPress installations, you have the capability to add a third, forth or more. For further exploration, why not try hosting other applications besides WordPress behind the Nginx proxy? Any software that is available as a Docker image and listens on port 80 is possible. This simple, yet powerful architecture is useful for hosting multiple containerized applications with a single IP, allowing you to do even more with fewer cloud instances.

My first post is a copy of another blog, just to get it saved for backup. Here is the source:

Leave a Reply

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