How to specify server port in dynamic configuration?

We are able to define the following label for the service:

traefik.http.services.myservice.loadbalancer.server.port=9000

What is the equivalent of the above line in file provider? I suppose it should be something like this, but I didn't find any documentation.

http:
  services:
    myservice:
      loadbalancer:
        server:
          port: 9000

Hello,

In the file provider, a server must be describe by an URL:

http:
  services:
    my-service:
      loadBalancer:
        servers:
          - url: "http://foobar.com:9080"

https://docs.traefik.io/v2.0/routing/services/#servers

The label traefik.http.services.myservice.loadbalancer.server.port exists because for a Docker container a user cannot known the IP.

Let's say I have the following dynamic configuration saved in file in config folder:

http:
  services:
    traefik:
      loadBalancer:
        passHostHeader: true
    whoami:
      loadBalancer:
        passHostHeader: true
        sticky:
          cookie:
            name: StickyCookie
  routers:
    traefik:
      rule: "Host(`example.com`)"
      entryPoints:
        - "traefik"
      service: traefik
    whoami:
      rule: "Host(`example.me`)"
      entryPoints:
        - "web"
      service: whoami

And the following docker-compose file:

version: "3.7"

services:
  traefik:
    image: "traefik:v2.0"
    networks:
      - traefik-net
    ports:
      - "9000:9000"
      - "5000:5000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./config/:/etc/traefik"
    deploy:
      replicas: 1
      labels:
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"

networks:
  traefik-net:
    external:
      name: traefik-net

When I execute docker stack deploy, it creates 3 services:

  1. traefik (provider file)
  2. traefik (provider Docker)
  3. whoami (provider file)

This is not what I want. I just want to specify port for traefik service which is defined in file, I don't want to create another service. How can I reference existing traefik service from labels section so that it wouldn't create new one?

Why are you using file you define routers on containers?
why not just use labels?


Only labels (I recommend):

version: "3.7"

services:
  traefik:
    image: "traefik:v2.0"
    networks:
      - traefik-net
    ports:
      - "9000:9000"
      - "5000:5000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./config/:/etc/traefik"
    deploy:
      replicas: 1
      labels:
        - "traefik.http.routers.traefik.rule=Host(`example.com`)"
        - "traefik.http.routers.traefik.entrypoints=traefik"
        - "traefik.http.routers.traefik.service=api@internal"
        - "traefik.http.services.traefik.loadbalancer.server.port=8080" # noop

  whoami:
    image: containous/whoami:v1.3.0
    networks:
      - traefik-net
    deploy:
      labels:
        - "traefik.http.routers.whoami.rule: Host(`example.me`)"
        - "traefik.http.routers.myrouter.entrypoints=web"
        - "traefik.http.services.whoami.loadbalancer.sticky.cookie.name=StickyCookie"

networks:
  traefik-net:
    external:
      name: traefik-net

Mixed labels and file (I don't recommend in your case):

version: "3.7"

services:
  traefik:
    image: "traefik:v2.0"
    networks:
      - traefik-net
    ports:
      - "9000:9000"
      - "5000:5000"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./config/:/etc/traefik"
    deploy:
      replicas: 1
      labels:
        - "traefik.enable=false"

  whoami:
    image: containous/whoami:v1.3.0
    networks:
      - traefik-net
    deploy:
      labels:
        - "traefik.http.services.whoami.loadbalancer.sticky.cookie.name=StickyCookie"

networks:
  traefik-net:
    external:
      name: traefik-net
http:
  routers:
    traefik:
      rule: "Host(`example.com`)"
      entryPoints:
        - "traefik"
      service: api@internal
    whoami:
      rule: "Host(`example.me`)"
      entryPoints:
        - "web"
      service: whoami@docker

It cannot be done by using only file.

I'm trying to do something similar to what is described in this topic and I was curious about the statement quoted above.

I've got an application consisting of multiple containers, all defined as http services. I also have one or a few containers that will need tcp services. My approach has been to use the dynamic config file to define all the services. My reasoning has been that I don't want to have the config done using labels in compose files, as I'd like the compose file(s) to be as clean as possible. Also, we will need to modify the host rules for different installations. Hence, I found it to be cleaner to have all the configuration in the dynamic file, since it seems like that is the purpose of that file.

I would greatly appreciate if you could shed some light on the above statement and maybe also comment on my strategy to provide routing/services for the application behind Traefik.

We run a tenant based SaaS. Every new customer gets their own service/instance.

So for every new customer we have a docker-compose.yml file which includes the labels for the new sub-domain.

In our case it’s easier to create only one file instead of having to update an additional dynamic config file.

Thanks for the input @bluepuma77. That seems to make sense in your case. Our product is not SaaS, so it's a little harder (read impossible) for us to control each instance. Also, the customer might need/want to be able to modify the installation, both in terms of what services to run and the config of each. So, it seems better and safer to have fewer files to modify, as we need to write configuration tooling to make that possible and safe to do in a running instance.

What stumps me is that when I try to add the tcp router/service in the dynamic config file, it doesn't work. It's not until I add back docker as a provider and use labels that I can get it to work. But, then of course, I also can't find any examples of a config.yml that include both http and tcp sections. The official documentation only shows how to do it with labels. Or I'm somehow not finding the right docs.

It should be no problem to use TCP or TCP+http routers in a regular dynamic config file, which you load with providers.file in static config.

For use with labels, maybe check simple Traefik TCP example.

The usual challenge is that TCP needs to use TLS/SSL to be routed and Traefik needs the cert to be able to decrypt the request. If Traefik does not have the cert or it’s plain TCP, then you can only use HostSNI(`*`) with a single service on that port.

Hi @bluepuma77, thanks for the input. I've been using HostSNI(*) in my testing and I finally got this to work (for the most part), using a dynamic config file, like config.yml. As noted in my original question/comment, for my use-case, I don't particularly care for or like to use labels, as that will "muddle" the structure of the application and mix in configs into my compose files. I need to keep those as clean as possible, reducing the need to modify anything in those and instead drive all settings into config files based on runtime configs. Hence, in my case it seems like a bad idea to use labels and carry those around and subsequently having to modify them for each installation. I see how that definitely could work in some situations, but not so much for what I'm working on.

Thanks again for your suggestions, as it helped me get on the right path.

It doesn’t really matter, dynamic config can be read from providers.file or providers.docker.

The latter will just auto-provide the target IP, which you have to set yourself in file.