Epidemiology & Technology

Traefik Ver 2.0 and Multiple WordPress Containers

There are already two docker networks in place – web, and internal

docker network ls 

NETWORK ID          NAME                DRIVER              SCOPE
XXXXXXXXXXXX       bridge              bridge              local
XXXXXXXXXXX        host                host                local
XXXXXXXXXXX        internal            bridge              local
XXXXXXXXXXX        none                null                local
XXXXXXXXXXX        web                 bridge              localCode language: JavaScript (javascript)

For reference, the commands used to create the newtworks were

docker network create web

docker network create --driver bridge internal
docker network inspect internal

Traefik Version 2.0

The containers is created using following files and storages

cd traefik
mkdir configuration
mkdir letsencrypt
touch configuration/dynamic_conf.toml
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json
touch docker-compose.yml
tree

├── docker-compose.yml
├── configuration
│   └── dynamic_conf.toml
├── letsencrypt
    └── acme.json

dockercompose.yml

version: "3.3"

services:
  traefik4:
    image: "traefik:latest"
    container_name: "traefik4"
    restart: "always"
    command:
      - "--global.sendAnonymousUsage"
        #- "--log.level=DEBUG"
      - "--log.filePath=/var/log/traefik.log"
      - "--accesslog=true"
      - "--accesslog.filePath=/var/log/access.log"
      - "--accesslog.bufferingsize=100"
        #- "--api.insecure=true"
        #- "--api=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/configuration"
      - "--providers.file.filename=dynamic_conf.toml"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
        #- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.mytlschallenge.acme.email=mymail@domain.com"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    volumes:
      - logs:/var/log
      - "./letsencrypt:/letsencrypt"
      - "./configuration:/configuration"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - web
    ports:
      - 80:80
      - 443:443

networks:
  web:
    external: true

volumes:
  logs: {}
Code language: YAML (yaml)

/configuration/dynamic_conf.toml – this file can be edited on the fly and it will be automatically reloaded

[http]

  [http.routers.my-api]
    entryPoints = ["websecure"]
    rule = "Host(`TRAEFIC_DASHBOARD.epidemiology.tech`)"
    service = "api@internal"
    middlewares = ["secured"]

    [http.routers.my-api.tls]
      options = "default"
      certResolver = "mytlschallenge"

  [http.middlewares]
 
    [http.middlewares.secured.chain]
      middlewares = ["safe-ipwhitelist", "auth"]

    [http.middlewares.secureHeader.headers]
      frameDeny = true
      sslRedirect = true
      stsSeconds = 31536000
      stsPreload = true
      stsIncludeSubdomains = true
      browserXssFilter = true
      contentTypeNosniff = true
      forceSTSHeader = true
  
    [http.middlewares.auth.basicAuth]
      users = [
        "USERNAME:HTPASSSWD_GENERATED_PASSWORD_FOR_TRAEFIC_DASHBOARD"
      ]

    [http.middlewares.safe-ipwhitelist.ipWhiteList]
      sourceRange = ["192.168.1.0/24", "XXX.XXX.XX.0/24"]

[tls]

  [tls.options]
    [tls.options.default]
      minVersion = "VersionTLS12"
      cipherSuites = [
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
      ]
      sniStrict = true
Code language: TOML, also INI (ini)

Here a ‘websecure‘ entry-point has been defined.

Please make sure to create DNS entries for the TRAEFIC DASHBOARD subdomain.

Also, the IPs from where the dashboard need to be accessed need to be whitelisted

To create password :

htpasswd -nb admin secure_password

Portainer Container

mkdir portainer
cd portainer
mkdir data
touch docker-compose.yml
tree

├── data
└── docker-compose.ymlCode language: CSS (css)

docker-compose.yml – runs on port 9000, so that also needs to be defined

version: '3'

services:
  portainer:
    image: portainer/portainer:latest
    container_name: portainer
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - web
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.portainer-https.redirectscheme.scheme=https"
      - "traefik.http.routers.portainer-http.entrypoints=web"
      - "traefik.http.routers.portainer-http.rule=Host(`portainerDomain.epidemiology.tech`)"
      - "traefik.http.routers.portainer-http.middlewares=portainer-https@docker"
      - "traefik.http.routers.portainer.middlewares=secureHeader@file"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.rule=Host(`portainerDomain.epidemiology.tech`)"
      - "traefik.http.routers.portainer.tls=true"
      - "traefik.http.routers.portainer.tls.options=default"
      - "traefik.http.routers.portainer.tls.certresolver=mytlschallenge"
      - "traefik.http.services.portainer.loadbalancer.server.port=9000"

networks:
  web:
    external: true
Code language: PHP (php)

MariaDb and Adminer

version: "3"

services:
  dbWP:
    image: mariadb:10.5
    environment:
#      MYSQL_USER: XXXXXXXXXXXXX 
#      MYSQL_PASSWORD: XXXXXXXXXXXXXXXX
#      MYSQL_DATABASE: XXXXXXXXXXXX
       MYSQL_RANDOM_ROOT_PASSWORD: '1'
    networks:
      - internal
    labels:
      - traefik.enable=false
    volumes:
      - ./datadir:/var/lib/mysql
      
  adminerWP:
    image: adminer:4.7.7-standalone
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.adminerWP-https.redirectscheme.scheme=https"
      - "traefik.http.routers.adminerWP-http.entrypoints=web"
      - "traefik.http.routers.adminerWP-http.rule=Host(`adminer.epidemiology.tech`)"
      - "traefik.http.routers.adminerWP-http.middlewares=adminerWP-https@docker"
      - "traefik.http.routers.adminerWP.middlewares=secureHeader@file"
      - "traefik.http.routers.adminerWP.entrypoints=websecure"
      - "traefik.http.routers.adminerWP.rule=Host(`adminer.epidemiology.tech`)"
      - "traefik.http.routers.adminerWP.tls=true"
      - "traefik.http.routers.adminerWP.tls.options=default"
      - "traefik.http.routers.adminerWP.tls.certresolver=mytlschallenge"
      - "traefik.http.services.adminerWP.loadbalancer.server.port=8080"
    networks:
      - internal
      - web
    depends_on:
      - dbWP
      
networks:
  web:
    external: true
  internal:
    external: true
Code language: YAML (yaml)

WordPress 1 –

Docker – “internal” network is used for MariaDB and “web” for the various clients connecting to the website

version: "3"

services:
  epidemiology:
    image: wordpress:5.4.2-apache
    environment:
      WORDPRESS_DB_HOST: dbWP
      WORDPRESS_DB_USER: XXXXXXXXXXXX
      WORDPRESS_DB_PASSWORD: XXXXXXXXXX
      WORDPRESS_DB_NAME: epidemiologywpblog1db
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.epidemiologytech-https.redirectscheme.scheme=https"
      - "traefik.http.routers.epidemiologytech-http.entrypoints=web"
      - "traefik.http.routers.epidemiologytech-http.rule=Host(`epidemiology.tech`, `www.epidemiology.tech`)"
      - "traefik.http.routers.epidemiologytech-http.middlewares=epidemiologytech-https@docker"
      - "traefik.http.routers.epidemiologytech.middlewares=secureHeader@file"
      - "traefik.http.routers.epidemiologytech.entrypoints=websecure"
      - "traefik.http.routers.epidemiologytech.rule=Host(`epidemiology.tech`, `www.epidemiology.tech`)"
      - "traefik.http.routers.epidemiologytech.tls=true"
      - "traefik.http.routers.epidemiologytech.tls.options=default"
      - "traefik.http.routers.epidemiologytech.tls.certresolver=mytlschallenge"

    volumes:
      - ./epi/wordpress_files:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    networks:
      - internal
      - web

networks:
  web:
    external: true
  internal:
    external: true
Code language: JavaScript (javascript)

WordPress 2

version: "3"

services:
  wpblog2db:
    image: wordpress:5.4.2-apache
    environment:
      WORDPRESS_DB_HOST: dbWP
      WORDPRESS_DB_USER: xxxxxxxxxxxx2222
      WORDPRESS_DB_PASSWORD: xxxxxxxxxxxxxx2222
      WORDPRESS_DB_NAME: wpblog2db
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.wpblog2-https.redirectscheme.scheme=https"
      - "traefik.http.routers.wpblog2-http.entrypoints=web"
      - "traefik.http.routers.wpblog2-http.rule=Host(`wpblog2.com`, `www.wpblog2.com`)"
      - "traefik.http.routers.wpblog2-http.middlewares=wpblog2-https@docker"
      - "traefik.http.routers.wpblog2.middlewares=secureHeader@file"
      - "traefik.http.routers.wpblog2.entrypoints=websecure"
      - "traefik.http.routers.wpblog2.rule=Host(`wpblog2.com`, `www.wpblog2.com`)"
      - "traefik.http.routers.wpblog2.tls=true"
      - "traefik.http.routers.wpblog2.tls.options=default"
      - "traefik.http.routers.wpblog2.tls.certresolver=mytlschallenge"
    volumes:
      - ./wordpress_files:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    networks:
      - internal
      - web

networks:
  web:
    external: true
  internal:
    external: trueCode language: JavaScript (javascript)

Related posts