Traefik2 End-To-End Tutorial

written 2020-04-20

Traefik2 is an Edge Router for your Services like Docker Containers. Unlike other reverse proxys Traefik comes with some nice additions like automatic service discovery and issuing of certificates. Unfortunaly there are few tutorials walking you through end to end.

Setting up Traefik

In most Tutorials Traefik itself is configured via labels, however I find it best to use a config file for clearity.

We begin with creating a docker network for our frontfacing services: docker network create traefik2_net. Next we create an empty file called acme.json here we will store the certificates. Important: This file has to have permisions set whith chmod 600 ./acme.json.

Traefik docker-compose

Next we will create the docker-compose file:

/traefik/docker-compose.yml


version: "3.3"

services:
  traefik:
    image: "traefik:v2.2" # Pin to a Version to avoid breaking changes
    container_name: "traefik" # Give the container a clear name
    restart: always # Always restart (unless-stoped is also ok!)
    ports:
      - "80:80"  # Listen on port 80
      - "443:443" # Listen on port 443
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro" # Read(-only) the Docker Socket 
      - "./traefik.toml:/etc/traefik/traefik.toml:ro"  # Read(-only) the Config File
      - "./acme.json:/acme.json"                       # A File to safe Certificates 
      - "./config.toml:/config.toml:ro"                # Further config file, also Read only

networks:                                              # Define a Front-Facing Network
  default:                                             # It's this containers default network
    external:                                          # It is not bound to this container
      name: traefik2_net                               # And its called traefik2_net

In this file we mentioned two config files we did not create yet. traefik.toml and config.toml we will get to them next.

Traefik config

The main config file is traefik.toml:

./traefik.toml

[log]
  level = "ERROR"           # Its a good Idea to have logs but we don't have to
[providers]
  [providers.docker]                         # Our Provider is Docker
    endpoint = "unix:///var/run/docker.sock" # And its Endpoint is the SockFile
    exposedByDefault = "false"          # We don't expose containers by default
  [providers.file]                   # Our second provider for aditional config
    filename = '/config.toml'
[entryPoints]
  [entryPoints.http] # Our entrypoints named http and https the names are yours to choose
    address = ":80"  # This entrypoint listens to everything on 80
  [entryPoints.https]
    address = ":443" # https listens on 443

[certificatesResolvers.le.acme] # Provider for Certs
  email="your@e-mail.example"   # your email is needed
  storage="acme.json"           # Here are the certs stored
  [certificatesResolvers.le.acme.tlsChallenge] # We will use the tls Challange

The congif.toml defines a middleware for https redirect:

./config.toml

[http.middlewares]
  [http.middlewares.redirectHttps.redirectScheme]
    scheme = "https"

Armed with this config Files we are finaly able to start Traefik with docker-compose up -d

Configuring A Service

Services are configured via labels in the docker-compose file. This example will contain a Database and a service listening to a diffrent port than port 80

docker-compose example

version: "3.7"
services:
  db: # The Database
    image: postgres:12
    environment:
      - PGDATA=/db-data
      - POSTGRES_PASSWORD=postgres
    volumes:
      - ./db:/db-data:rw
    # The Database will only connect to the backend Network
    networks:
      - backend 
  app:
    image: example

    command: bash -c 'gunicorn example.wsgi -b :8080 --log-level=info'
    # Here we will configure Traefik with;
    labels:
      # This will make the service visible for Traefik
      - "traefik.enable=true"  
      # The Traefik Network is this Network and not backend                    
      - "traefik.docker.network=traefik2_net"    
      # This is the hostname we want use for http
      - "traefik.http.routers.example.rule=Host(`example.bithive.space`)" 
      # The Entrypoint is http (as defined in traefik.toml)  
      - "traefik.http.routers.example.entrypoints=http"     
      # We want to have certs via our resolver defined in traefik.toml
      - "traefik.http.routers.example.tls.certresolver=le"  
      # We want to redirect all trafic via our middleware defined in the file provider
      - "traefik.http.routers.example.middlewares=redirectHttps@file"    

      # We will also listen on https:
      - "traefik.http.routers.example-https.entrypoints=https"
      # We will use certs for this connection
      - "traefik.http.routers.example-https.tls=true"
      # This is the host for https
      - "traefik.http.routers.example-https.rule=Host(`example.bithive.space`)"
      # Oh and we want to use a diffrent port than 80
      - "traefik.http.services.exaple.loadbalancer.server.port=8080"
    depends_on:
      - db
    networks:
      # This service will be connected to the backend and the traefik2_net
      - traefik2_net 
      - backend


networks:
  traefik2_net:
    external:
      name: traefik2_net
  backend:

Conclusion

With this config the service is discoverable by Traefik and it can talk to its database but no other service will be able to talk to its databases. It will redirect http requests to https and secure the connection with a Let’s Encrypt Certificate.

There is no comment system. If you want to contact me about this article, you can do so via e-mail or Mastodon.