Setup Multiple WordPress Sites Using Docker Compose (Traefik + MariaDB)

Prerequisite

Run below CLI to check if everything is installed properly.

docker compose version

Setup Traefik with Docker Compose

Let’s first create a folder for Traefik reverse proxy.

mkdir ~/traefik && cd ~/traefik

Next we need to create network for Traefik to communicate with other containers, and it should be exposed externally.

docker create network traefik

Now, let’s create docker-compose.yml

vi docker-compose.yml
networks:
  traefik:
    external: true

volumes:
  traefik-certificates:

services:
  traefik:
    image: "traefik:latest"
    command:
      - "--log.level=DEBUG"
      - "--accesslog=true"
      - "--api.dashboard=true"
      - "--api.insecure=true"
      - "--ping=true"
      - "--ping.entrypoint=ping"
      - "--entryPoints.ping.address=:8082"
      - "--entryPoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entryPoints.websecure.address=:443"
      - "--providers.docker=true"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedByDefault=false"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      # For requesting dev cert (if prod cert has issue during development)
      # - "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@bill-min.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - traefik-certificates:/etc/traefik/acme
    networks:
      - traefik
    ports:
      - "80:80"
      - "443:443"
    healthcheck:
      test: ["CMD", "wget", "http://localhost:8082/ping","--spider"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 5s
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.your-domain.com`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls=true"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.middlewares=authtraefik"
      - "traefik.http.middlewares.authtraefik.basicauth.users=your_username:{SHA}your_hash"
    restart: unless-stopped

Above config also adds Traefik Dashboard and https with letsencrypt.

Replace your-domain with your actual domain name and setup correct DNS.

Replace your_username and {SHA}your_hash with ones generated from https://hostingcanada.org/htpasswd-generator/

Finally, lets start Traefik container.

docker compose up -d

Verify the container is running successfully

docker ps

You can also check Traefik dashboard by visiting https://traefik.your-domain.com. (you will need to enter the username and password used when generating htpasswd)

Setup first wordpress site

First, we need to create an internal network for communicating between wordpress and db (MariaDB in this tutorial).

docker create network my-wp-1

Then lets create new folder for each site we are building.

mkdir ~/my-wp-1 && cd ~/my-wp-1

Create docker-compose.yml.

networks:
  my-wp-1:
  traefik:
    external: true
 
volumes:
  mariadb-data:
 
services:
  mariadb:
    image: mariadb:latest
    volumes:
      - mariadb-data:/var/lib/mysql
    environment:
      MARIADB_DATABASE: ${WORDPRESS_DB_NAME}
      MARIADB_USER: ${WORDPRESS_DB_USER}
      MARIADB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      MARIADB_RANDOM_ROOT_PASSWORD: "1"
    networks:
      - my-wp-1
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 60s
    restart: unless-stopped
 
  wordpress:
    image: wordpress:latest
    volumes:
      - ./wordpress-files:/var/www/html
    environment:
      WORDPRESS_DB_HOST: mariadb:3306
      WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
      WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
      WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
    networks:
      - my-wp-1
      - traefik
    healthcheck:
      test: timeout 10s bash -c ':> /dev/tcp/127.0.0.1/80' || exit 1
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.my-wp-1.rule=Host(`${WORDPRESS_HOSTNAME}`)"
      - "traefik.http.routers.my-wp-1.service=my-wp-1"
      - "traefik.http.routers.my-wp-1.entrypoints=websecure"
      - "traefik.http.services.my-wp-1.loadbalancer.server.port=80"
      - "traefik.http.services.my-wp-1.loadbalancer.passhostheader=true"
      - "traefik.http.routers.my-wp-1.tls=true"
      - "traefik.http.routers.my-wp-1.tls.certresolver=letsencrypt"
      - "traefik.http.routers.my-wp-1.middlewares=compresstraefik"
      - "traefik.http.middlewares.compresstraefik.compress=true"
      - "traefik.docker.network=traefik"
    restart: unless-stopped
    depends_on:
      mariadb:
        condition: service_healthy

Also we need to create .env file for setting up some variables. (Replace values with proper ones)

WORDPRESS_HOSTNAME=www.your-domain.com
WORDPRESS_DB_NAME=wordpressdb
WORDPRESS_DB_USER=myuser
WORDPRESS_DB_PASSWORD=mypassword

Then we should be able to start wordpress.

docker compose up -d

Now we should be able to visit https://www.your-domain.com to start using WordPress.

Create more wordpress sites

Simply repeat the steps we used to create our first site to create more sites, just need to change my-wp-1 to different value in docker-compose.yml and change values in .env file then run docker compose up -d.

Comments

Leave a Reply

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