Routing inside Docker Swarm using Worker Hostname

Hey,
i have a am trying to scale a Large application. My Problem is, that I don't know how to configure Traefik the way I need to.
In my Special Usecase I need scale 3 Docker container to over 100 Nodes. I can put a configuration Files on each Docker Worker.
I want, that the Subdomain of the Containers on every Node is based on a configuration File / Environment.
A example dockerfile can look like this_

version: "3"
services:
  agent65:
    image: containous/whoami
    networks:
      - proxy
    deploy:
      mode: global
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.myapp.service=myapp_service"
        - "traefik.http.services.myapp_service.loadbalancer.server.port=80"
        - "traefik.http.routers.myapp.rule=Host(`{{ node_name }}.example.com`)"
        - "traefik.http.routers.myapp.tls=true"
        - "traefik.http.routers.myapp.tls.certresolver=lets-encrypt"
networks:
  proxy:
    driver: overlay
    external: true```
The Problem right now is, that I have no idea how to configure the {{ node_name }} part. I also don't know if it is possible.
I'm using docker-swarm, because the Server are not in the Internet. It's a closed Network.
In Theory I could write a script to automatically generate a Hughe docker-compose. But I want to avoid that. Any ideas?

We use this notation with stack deploy to set the container hostname automatically:

# docker-compose.yml
version: '3.9'

services:
  traefik:
    image: traefik:v2.9.6
    command: --configFile=/traefik.yml
    hostname: '{{.Node.Hostname}}'

This should probably work with deploy mode:global (with constraints) to have node_name in a label. If you want your 3 containers on the same node to connect, you can maybe use an env var like DB=db-{{.Node.Hostname}}.example.com to reference each other.

How do you handle the SSL Certificate? As soon as I do your solution, I get the following exception:

time="2023-01-27T17:04:52Z" level=info msg="Configuration loaded from file: /traefik.toml"
time="2023-01-28T11:42:24Z" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"{{.node.hostname}}.example.com\" is not a valid hostname"
time="2023-01-28T11:42:24Z" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"{{.node.hostname}}.example.com\" is not a valid hostname"
time="2023-01-28T11:42:25Z" level=error msg="Unable to obtain ACME certificate for domains \"{{.node.hostname}}.example.com\": unable to generate a certificate for the domains [{{.node.hostname}}.example.com]: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for \"{{.node.hostname}}.example.com\": Domain name contains an invalid character" providerName=lets-encrypt.acme routerName=myapp@docker rule="Host(`{{.Node.Hostname}}.example.com`)" ACME CA="https://acme-v02.api.letsencrypt.org/directory"
time="2023-01-28T11:43:24Z" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"{{.node.hostname}}.example.com\" is not a valid hostname"
time="2023-01-28T11:43:24Z" level=error msg="Error while adding route for host: invalid value for \"HostSNI\" matcher, \"{{.node.hostname}}.example.com\" is not a valid hostname"
time="2023-01-28T11:43:24Z" level=error msg="Unable to obtain ACME certificate for domains \"{{.node.hostname}}.example.com\": unable to generate a certificate for the domains [{{.node.hostname}}.example.com]: acme: error: 400 :: POST :: https://acme-v02.api.letsencrypt.org/acme/new-order :: urn:ietf:params:acme:error:rejectedIdentifier :: Error creating new order :: Cannot issue for \"{{.node.hostname}}.example.com\": Domain name contains an invalid character" ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=lets-encrypt.acme routerName=myapp@docker rule="Host(`{{.Node.Hostname}}.example.com`)"

Using the following configuration:


version: "3"
services:
  agent65:
    image: containous/whoami
    networks:
      - proxy
    deploy:
      mode: global
      placement:
        constraints: [node.hostname == test-server-1]
      labels:
          - "traefik.enable=true"
          - "traefik.http.routers.myapp.service=myapp_service"
          - "traefik.http.services.myapp_service.loadbalancer.server.port=80"
          - "traefik.http.routers.myapp.rule=Host(`{{.Node.Hostname}}.example.com`)"
          - "traefik.http.routers.myapp.tls=true"
          - "traefik.http.routers.myapp.tls.certresolver=lets-encrypt"

networks:
  proxy:
    driver: overlay
    external: true

Your config has Host(), but the error is about HostSNI(). Seems the values have not been substituted, did you use docker stack deploy? Not sure if substitution works without it.

Yeah. The command was

docker stack deploy -c docker-compose.yml test