Setting priority in a file based route

I have two routes of the same length. I would like to prioritize one over the other however I am unable to understand the syntax for doing this.

My two routes are:

  • Host(localhost) && Path(/)
  • Host(localhost) && PathPrefix(/)

I want the first route to route to the landing page of my web site. I have put together a small example using the whoami container to simulate my landing page.

version: '3.2'
services:

  traefik:
    image: traefik:2.0.1
    command:
        - --api.insecure=true
        - --providers.docker.swarmMode=true
        - --providers.docker.exposedbydefault=false
        - '--providers.docker.defaultrule=Host(`localhost`) &&  PathPrefix(`/{{ .Name | trimPrefix (index .Labels "com.docker.stack.namespace") | trimPrefix "_" | trimPrefix "-" }}`)'
        - --entrypoints.http.address=:80
        - --providers.file.directory=/config
        - --providers.file.watch=true
        # Uncomment portions of the following section if you require detailed logging.
        # - --log.level=DEBUG
        # - --log.format=json
        - --accesslog.filepath=/logs/access.log
        - --log.filepath=/logs/traefik.log
    deploy:
        labels:
            - traefik.enable=true
            - traefik.http.routers.traefik.entrypoints=http
            - traefik.http.middlewares.strip-prefix.chain.middlewares=strip-prefix-1,strip-prefix-2
            - traefik.http.middlewares.strip-prefix-1.redirectregex.regex=^(https?://[^/]+/[a-z0-9_]+)$$
            - traefik.http.middlewares.strip-prefix-1.redirectregex.replacement=$${1}/
            - traefik.http.middlewares.strip-prefix-1.redirectregex.permanent=true
            - traefik.http.middlewares.strip-prefix-2.stripprefixregex.regex=/[a-z0-9_]+ 
            - traefik.http.services.traefik.loadbalancer.server.port=8080           

    ports:
        - "80:80"
        - "8199:8080"
    volumes:
        - "/var/run/docker.sock:/var/run/docker.sock:ro"
        - "${PWD}/config:/config"
        - "${PWD}/logs:/logs"
  whoami:
    image: "containous/whoami"
    deploy:
      labels:
        - traefik.enable=true
        - traefik.http.routers.whoami.entrypoints=http
        - traefik.http.routers.whoami.middlewares=strip-prefix
        - traefik.http.services.whoami.loadbalancer.server.port=80

  nginx:
    image: "nginx:latest"
    deploy:
      labels:
        - traefik.enable=true
        - traefik.http.routers.nginx.rule=Host(`localhost`) && PathPrefix(`/`)
        - traefik.http.routers.nginx.entrypoints=http
        - traefik.http.routers.nginx.middlewares=strip-prefix
        - traefik.http.services.nginx.loadbalancer.server.port=80

I have an additional file based route for Path(/) defined with this configuration:

http:
  routers:
    landingPage:
      entryPoints:
        - "http"
      rule: "Host(`localhost`) && Path(`/`)"
      service: "whoami@docker"
      middlewares: ["landingPage"]
      priority: 5
  middlewares:
      landingPage:
          replacePath:
            path: "/landingPage"

Note the priority of the route is set to 5

I tested this with the following sequence:

$  docker-compose config | docker stack deploy -c - traefik 
WARNING: Some services (nginx, traefik, whoami) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
Creating network traefik_default
Creating service traefik_nginx
Creating service traefik_traefik
Creating service traefik_whoami
$ curl -L -s http://localhost | grep "title\|landingPage" 
<title>Welcome to nginx!</title>
$ docker service scale traefik_nginx=0
traefik_nginx scaled to 0
overall progress: 0 out of 0 tasks 
verify: Service converged 
$ curl -L -s http://localhost | grep "title\|landingPage" 
GET /landingPage HTTP/1.1

The first invocation of curl after the stack has been started routes to the Nginx server. When the Nginx server is scaled to zero, the landing page route works as expected.

I was expecting the priority of the landing page route to have that route considered first before the catchall route of PathPrefix(/).

Have I misunderstood the usage of the priority attribute within routes? Is there another way to accomplish what I have described?

Hello,

version: '3.2'
services:

  traefik:
    image: traefik:2.0.2
    command:
      - --api=true
      - --entrypoints.web.address=:80
      
      - --providers.docker=true
      - --providers.docker.swarmMode=true
      - --providers.docker.exposedbydefault=false
      - '--providers.docker.defaultrule=Host(`localhost`) &&  PathPrefix(`/{{ .Name | trimPrefix (index .Labels "com.docker.stack.namespace") | trimPrefix "_" | trimPrefix "-" }}`)'
      # - --providers.file.directory=/config
      # - --providers.file.watch=true
      
      # Uncomment portions of the following section if you require detailed logging.
      # - --log.level=DEBUG
      # - --log.format=json
      - --log.filepath=/logs/traefik.log
      
      - --accesslog.filepath=/logs/access.log
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # - "${PWD}/config:/config"
      - "${PWD}/logs:/logs"
    deploy:
      labels:
        - traefik.enable=true
        - traefik.http.routers.traefik.rule=Host(`traefik.localhost`)
        - traefik.http.routers.traefik.entrypoints=web
        - traefik.http.routers.traefik.service=api@internal
        - traefik.http.services.traefik.loadbalancer.server.port=999 # noop
  
  whoami:
    image: "containous/whoami"
    deploy:
      labels:
        - traefik.enable=true

        # landingPage
        - traefik.http.routers.landingPage.rule=Host(`localhost`) && Path(`/`)
        - traefik.http.routers.landingPage.priority=5
        - traefik.http.routers.landingPage.entryPoints=web

        # service
        - traefik.http.services.landingPage.loadbalancer.server.port=80

  nginx:
    image: "nginx:latest"
    deploy:
      labels:
        - traefik.enable=true

        # basic
        - traefik.http.routers.nginx.rule=Host(`localhost`) && PathPrefix(`/`)
        - traefik.http.routers.nginx.priority=1
        - traefik.http.routers.nginx.entrypoints=web
        - traefik.http.routers.nginx.middlewares=strip_prefix
        
        # middlewares
        - traefik.http.middlewares.strip_prefix.stripprefixregex.regex=/[a-z0-9_]+ 

        # service
        - traefik.http.services.nginx.loadbalancer.server.port=80

https://docs.traefik.io/v2.0/routing/routers/#priority

The documentation you allude to, and which I was already aware of looks like this:

I did not notice that the green How default priorities are computed panel also expands and provides an explanation of the algorithm. On first reading it just looked like a title header rather than a spring loaded container for additional information.

Thanks