Combining host based and path based routing

Hello everyone,

we're currently in the process of finishing a university project. Our task was to create a microservice based application, so we started our crude prototype. The major challenge we're facing right now is to connect these services and make them accessible for our android and web client. Traefik seemed like a great option for that, so we decided to try it. We're running our app on a Docker Swarm cluster with four containers. So far the setup has been running smoothly, but no I'm starting to face some issues and I hope someone here can help me with them.
We have bunch of services that should be accessible under api.ourdomain.tld. To be able to route the requests to the right service we wanted to use path. Right now, the idea is toe use the following routing

  • api.ourdomain.tld/profiles -> Profile Service
  • api.ourdomain.tld/plane -> Inventory Service
  • *ourdomain.tld/ * -> Webapp Container (including assets)

I did some research and found out that the best option would be to combine the Host(api.ourdomain.tld) rule and the PathPrefix. I found this guide on migrating to v2 and tried to implement that into our setup.
The compose file we came up with looks like that.

version: "3"
services:
  proxy:
    image: traefik:2.2
    volumes: 
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    command: 
      - --api.insecure
      - --providers.docker
      # - --providers.docker.swarmMode=true
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --log
    networks: 
      - main
    deploy:
      mode: global
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
  bookingService:
    image: booking-service/dev
    ports:
      - 8092:8080
    networks: 
      - main
    environment: # reduced for readability
    labels: 
      - "traefik.http.routers.profileService.rule=Host(`api.ourdomain.tld`) && PathPrefix(`/plane`)"
      - treafik.http.routers.profileService.entrypoints=web
      - traefik.http.services.profileService.loadbalancer.server.port=8080
  webapp:
    image: our-webapp:latest
    ports:
      - 8081:80
    networks:
      - main
    labels: 
      - traefik.http.routers.webapp.rule=Host(`ourdomain.tld`)
      - traefik.http.services.webapp.loadbalancer.server.port=80
networks: 
  main:
    driver: overlay

(I know that the port mappings shoult not exist in a production setup, we're just using them to check the service individually. they won't be mapped in the final setup)

When I open the web dashboard, none of those rules will show up. Only the default mappings like Host(profileService-project-deployment) exist.

Am I missing something basic here? Can someone help me to fix my config or point me into the right direction? I appreciate any comment!

Thank you in advance

Common error when using swarm, the labels need to be nested under the deploy section. Traefik swarm uses the label of the service not the container labels.

https://docs.traefik.io/providers/docker/#routing-configuration-with-labels_1

Thank you for your fast reply! I tried changing that, my compose.yml now looks like that.

  bookingService:
    image: booking-service/dev
    ports:
      - 8092:8080
    networks: 
      - main
    deploy:
      labels: 
        - "traefik.http.routers.profileService.rule=Host(`api.ourapp.tld`) && PathPrefix(`/plane`)"
        - treafik.http.routers.profileService.entrypoints=web
        - traefik.http.services.profileService.loadbalancer.server.port=8080
  webapp:
    image: registry.gitlab.com/dhbw-codemonkeys/flyventure-web:latest
    ports:
      - 8081:80
    networks:
      - main
    labels: 
      - traefik.http.routers.webapp.rule=Host(`ourapp.tld`)
      - traefik.http.services.webapp.loadbalancer.server.port=80

I test the setup with docker stack deploy -c compose.yml ourproject. The mapping for the web section works Host(ourapp.tld), but the rule under deploy.labels for the booking service does not.
I tested the webapp mapping using curl -H Host:ourapp.tld http://localhost and it did reply as expected

I don't think it matters but you could try () around the rule.

Also check the docker logs for the traefik container and see if any related errors or warnings are logged.

Thank you so much! Adding the deploy labels actually helped after I fixed the other issue. For some reason some of my service containers were constantly crashing and and being restored. The gap between crashing and restoring caused the containers and their respective rules to not show up in the dashboard and a gateway timeout error being thrown.
After I fixed my containers and rebuilt them they were stable and the traefik rules defined in the deploy.labels were applied

1 Like