Reuse repetitive labels?

In Traefik 1.x I used to use anchor tags to reuse things like entrypoints, middleware, and headers. In 2.x, it doesn't seem like that is possible because you need to explicitly define unique routers/services for every single container, like this:

labels:
      traefik.http.routers.api.rule: host(`api.${LOCAL_DOMAIN}`)
      traefik.http.routers.api.entrypoints: http
      traefik.http.routers.api-secure.entrypoints: https
      traefik.http.routers.api-secure.tls: true
      traefik.http.routers.api-secure.tls.certResolver: letsencrypt
      traefik.http.routers.api-secure.middlewares: auth
      traefik.http.routers.api-secure.rule: host(`api.${DOMAIN}`)
      traefik.http.services.api.loadBalancer.server.port: 8080

Most of this information should be able to be abstracted into something like reusable anchor tags, and be left with just the "unique" labels like:

labels:
      traefik.http.routers.api.rule: host(`api.${LOCAL_DOMAIN}`)
      traefik.http.routers.api-secure.rule: host(`api.${DOMAIN}`)
      traefik.http.services.api.loadBalancer.server.port: 8080

I have ~15 different containers with almost exactly the same configuration for each one, so using anchor tags allowed me to make big changes to all of them at once. With 2.x, I have to repetitively change every single set of labels to make changes to all the containers, because you can't abstract away the unique router/service names.

Any ideas on how to remedy this?

Hello,

you can:

  • remove traefik.http.routers.api-secure.tls: true because traefik.http.routers.api-secure.tls.certResolver: letsencrypt is enough
  • abstract the rule of one router by using defaultRule
  • remove traefik.http.services.api.loadBalancer.server.port: 8080 if you are not using swarm and if the Dockerfile of the app already expose one port.

By example:

services:

  traefik:
    image: traefik:v2.0.1
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --providers.docker=false
      - '--providers.docker.defaultrule=Host(`{{ .Name }}.domain.localhost`)'
      # ...
    ports:
      - 80:80
      - 443:443
    # ...

  api:
    image: containous/whoami:v1.3.0
    labels:
      traefik.http.routers.api.entrypoints: web

      traefik.http.routers.api-secure.rule: Host(`api.${DOMAIN}`)
      traefik.http.routers.api-secure.entrypoints: websecure
      traefik.http.routers.api-secure.tls.certResolver: letsencrypt
      traefik.http.routers.api-secure.middlewares: auth@docker
      
      # traefik.http.services.api.loadBalancer.server.port: 80

Thanks Idez!

This is certainly better, and is probably good enough for my needs right now, though it's still unfortunate that a few of the labels can't be abstracted away. Ideally, there would be some kind of "namespaced" label, where you could just do something like:

traefik.http.namespaced-routers.api.entrypoints: web
traefik.http.namespaced-routers.api.entrypoints: websecure

And these labels could be copied verbatim to different containers, or put in anchor tags, without causing duplicate router errors (because the routers would be "namespaced" under their respective container). This would allow complete abstraction, rather than trying to cut away at little bits incrementally.

I guess this is more of a feature suggestion, assuming that level of abstraction isn't possible at the moment.

Thanks a lot

3 Likes