A week ago I decided to play around with Traefik because it seems to be pretty popular for Docker apps since it provides Docker support out of the box. I'm still amazed how easy it was to set it up so I decided to share my experience here in a series of posts.

Today's post will present my Traefik docker-compose.yml from my Ansible role which I use for automatic configurations of my web servers. It basically consists of a systemd service that simply spins up a Traefik Docker service via docker-compose.

Configure Traefik via Docker labels

Traefik provides mutliple ways to specify its configuration:

  • TOML
  • YAML
  • CLI

In this post I will only focus on CLI commands because those can be directly used within a docker-compose.yml file.

There are 2 types of configurations in Traefik: static and dynamic.

The Traefik documentation always displays the CLI version for static ones. These ones you just append to the command: section in your compose file, e.g.:

      - --entrypoints.websecure.address=:443
      - --entrypoints.web.address=:80

Dynamic configurations can be specified via the labels: section in a compose file, e.g.:

      - "traefik.http.routers.traefik.rule=Host(`example.com`)"

It's especially this label-approach which made the transition from Nginx to Traefik extremely easy. Once I had the Traefik container running, all it took me to do on my remaining Docker web apps was to update their compose file by adding a few labels and restart the services. Unfortunately the documentation regarding the labels-syntax is not really documented. However, it can be guessed from the YAML/TOML version.

Also note, there are two pretty good Traefik blog posts introducing Traefik 2.0 with Docker:

I suggest to read to through these articles since my article here is just a shorter version of those (I used those articles myself to create my Traefik container below).

Traefik docker-compose file

I will jump right into it and present my compose file before explaining the most important parts:

version: "3.8"

    container_name: traefik
    image: "{{ traefik_img }}"
      - --entrypoints.websecure.address=:443
      - --entrypoints.web.address=:80
      - --providers.docker=true
      - --api
      - --certificatesresolvers.le.acme.email=mail@example.com
      - --certificatesresolvers.le.acme.storage=/acme/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
      - "80:80"
      - "443:443"
      - traefik
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "$PWD/acme:/acme"
      # Dashboard
      - "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=admin"
      - "traefik.http.routers.traefik.tls.certresolver=le"
      - "traefik.http.middlewares.admin.basicauth.users=userXY:pwXY"
      # global redirect to https
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.redirs.entrypoints=web"
      - "traefik.http.routers.redirs.middlewares=redirect-to-https"

    name: traefik

The static configuration (under the command: seciton) specifies to

  • listen to ports 80 (http) and 443 (https)
  • watch out for Docker container labels to retrieve its routing configuration (--providers.docker=true). For that reason we also bind-mount the docker socket into the container (under the volumes: section).
  • expose its fancy dashboard so we can look at it (--api)
  • use LetsEncrypt for TLS encryption and specify the path to the configuration file that will hold all key/certs etc. (for more info on that see Traefik 2 & TLS 101). Additionally, we bind-mount the config file from the current working directory (again specified under volumes).

That's it regarding the static configuration. We now just provide a few additional dynamic configs as labels. We tell it to

  • route the dashboard to traefik.example.com
  • any requests received at traefik.example.com will be further routed to a service called api@internal
  • we want the dashboard somewhat secured, so we add a middleware called "admin" and to that middleware we attach a basic-auth for a given user & password (make sure to encode your password as described in the documentation; another imoprtant hint: you must prepend dollar signs in your encoded password with another dollar sign, e.g. ab$c -> ab$$c).
  • because we will need to provide user login data at the basic auth, we want to use TLS with a certresolver called le.

This would be already enough to have Traefik up and running with its dashboard published at traefik.example.com. However, because I already had a running Nginx reverse-proxy that redirected all http requests to https I wanted to have the same settings in Traefik. That what the last block of labels does which is marked with the corresponding inline-comment.

What's next

In a next post, I will share how I only had to set a few labels to my already existing docker-compose.yml file (that actually contains the Docker services running this blog / website) in order to finalize the migration from Nginx to Traefik.

Getagged mit:
Docker Traefik
blog comments powered by Disqus