Skip to main content

Traefik - Docker Compose, Reverse Proxy with Wildcard Certificate for Docker Containers

706 words·
Traefik Reverse Proxy Docker-Compose

Traefik Reverse Proxy with Wildcard Certificate
#

Docker Network
#

# Create network used for Traefik to communicate with other Docker containers
sudo docker network create traefik


# List Docker networks
sudo docker network ls

# Shell output:
NETWORK ID     NAME      DRIVER    SCOPE
320e7c072ce3   bridge    bridge    local
57b4c90cd6b4   host      host      local
8da6339e75ef   none      null      local
368d87821b79   traefik   bridge    local # Traefik network should be available now

Folder Structure
#

# Create folder structure
sudo mkdir -p /opt/traefik/certs && cd /opt/traefik/

Docker Compose
#

# Create Docker Compose file
sudo vi docker-compose.yml
version: '3'
services:
  reverse-proxy:
    image: traefik:v2.10
    container_name: Traefik-Reverse-Proxy
    restart: unless-stopped
    command:
      - --api.insecure=true # Enable Traefik Dashboard
      - --providers.docker
      - --providers.file.directory=/etc/traefik/dynamic
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080" # Traefik Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # Allow Traefik can listen to the Docker events
      - ./tls-configuration.yaml:/etc/traefik/dynamic/tls-configuration.yaml # Mount dynamic configuration
      - ./certs/:/etc/certs/ # Wildcard certificate directory
    networks:
      - traefik # Attach service to "traefik" network

networks:
  traefik:
    external: true # Network is created outside of this Docker Compose file

Note: Mounting of the Docker socket into the Traefik container enables dynamic reverse proxy configurations based on the state of Docker services.

  • Without comments
version: '3'
services:
  reverse-proxy:
    image: traefik:v2.10
    container_name: Traefik-Reverse-Proxy
    restart: unless-stopped
    command:
      - --api.insecure=true
      - --providers.docker
      - --providers.file.directory=/etc/traefik/dynamic
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./tls-configuration.yaml:/etc/traefik/dynamic/tls-configuration.yaml
      - ./certs/:/etc/certs/
    networks:
      - traefik

networks:
  traefik:
    external: true

Traefik Dynamic Configuration
#

# Create file for dynamic configuration
sudo vi tls-configuration.yaml
# tls-configuration.yaml
tls:
  certificates:
    - certFile: /etc/certs/fullchain.pem
      keyFile: /etc/certs/privkey.pem

Note: The Let’s Encrypt wildcard certificates fullchain.pem & privkey.pem must be placed inside the /opt/traefik/certs directory before the Docker stack is started.

# Place the certificates
sudo cp fullchain.pem privkey.pem /opt/traefik/certs

Start Docker Compose Container
#

# Start Docker Compose Container
sudo docker compose up -d

Traefik Dashboard
#

Dashboard: http://192.168.30.90:8080/dashboard/#/


Containers Behind Revers Proxy
#

Example: Whoami
#

Folder Structure
#

# Create folder structure
sudo mkdir -p /opt/whoami && cd /opt/whoami/

Docker Compose
#

# Create Docker Compose file
sudo vi docker-compose.yml
version: '3'
services:
  whoami:
    image: "traefik/whoami"
    container_name: "whoami"
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=websecure" # Create "whoami" router listening on the websecure entrypoint
      - "traefik.http.routers.whoami.tls=true" # Force https
      - "traefik.http.routers.whoami.rule=Host(`whoami.jklug.work`)" # Define domain name for service
      - "traefik.http.services.whoami-service.loadbalancer.server.port=80" # Use correct container port
      - "traefik.docker.network=traefik" # Define Docker network for traefik
    networks:
      - traefik # Attach service to "traefik" network

networks:
  traefik:
    external: true # Network is created outside of this Docker Compose file
  • Without comments
version: '3'
services:
  whoami:
    image: "traefik/whoami"
    container_name: "whoami"
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.jklug.work`)"
      - "traefik.http.services.whoami-service.loadbalancer.server.port=80"
      - "traefik.docker.network=traefik"
    networks:
      - traefik

networks:
  traefik:
    external: true

Start Docker Compose Container
#

# Start Docker Compose Container
sudo docker compose up -d

DNS Entry
#

# Create a DNS or Hosts entry that point to the IP of the server
192.168.30.90 whoami.jklug.work

Open Webinterface
#

# Open Whoami webinterface
https://whoami.jklug.work/

Example Multi Container Stack
#

Docker Compose File
#

version: "2.4"
services:
  db:
    image: ...
    ...
    labels:
      - "traefik.enable=false" # Disable Traefik
    networks:
      - intern # Define Docker stack network

  docker-app:
    depends_on:
      - db
    image: ...
    ...
    ports:
      - "1234"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.docker-app.entrypoints=websecure"
      - "traefik.http.routers.docker-app.tls=true"
      - "traefik.http.routers.docker-app.rule=Host(`docker-app.jklug.work`)"
      - "traefik.http.services.docker-app-service.loadbalancer.server.port=1234" # Define correct port
      - "traefik.docker.network=traefik"
    networks:
      - intern # Define Docker stack network
      - traefik # Define reverse proxy network

networks:
  traefik: # Define reverse proxy network: External network
    external: true
  intern: # Define internal Docker stack network

Docker Network
#

Note: Docker Compose generates a default project name based on the name of the directory where the docker-compose.yml file is located. This project name is then used as a prefix for the internal Docker network names.

# List Docker networks
sudo docker network ls

# Shell output:
...
8a176374d4c8   my-docker-stack_intern   bridge    local

HTTP to HTTPS Redirection
#

version: "2.4"
services:

  docker-app:
    image: ...
    ...
    ports:
      - "1234"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik"
      - "traefik.http.services.kimai-service.loadbalancer.server.port=1234"
      # HTTPS Router
      - "traefik.http.routers.docker-app.entrypoints=websecure"
      - "traefik.http.routers.docker-app.tls=true"
      - "traefik.http.routers.docker-app.rule=Host(`docker-app.jklug.work`)"
      # HTTP Router
      - "traefik.http.routers.docker-app-http.rule=Host(`docker-app.jklug.work`)"
      - "traefik.http.routers.docker-app-http.entrypoints=web"
      - "traefik.http.routers.docker-app-http.middlewares=redirect-to-https"
      # Middleware for HTTP to HTTPS redirection
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    networks:
      - intern
      - traefik

networks:
  traefik:
    external: true
  intern:

Links #

# Traefik Official Documentation
https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/