Category: Wordpress

  • 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.