10

Here's my docker-compose.yml:

version: '3'
services:
  website:
    build: ./website
    expose: [3000]
    labels:
      - "traefik.frontend.rule=Host:localhost"
  blog:
    build: ./blog
    expose: [4000]
    labels:
      - "traefik.frontend.rule=Host:localhost;PathPrefix:/blog"
  docs:
    build: ./docs
    expose: [3000]
    labels:
      - "traefik.frontend.rule=Host:localhost;PathPrefix:/docs"
  proxy:
    image: traefik
    command: --api.insecure=true --providers.docker
    networks:
      - webgateway
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

networks:
  webgateway:
    driver: bridge

What I want is access three different node.js websites via different routes. But these three node.js websites actually expose different ports. Now my treafik is running. I can config via localhost:8080 But localhost localhost/blog and localhost/docs are all 404 page not found

P.S: I'm not sure whether port is the issue I should investigate, because changing one node.js service to port 80 doesn't solve the puzzle. And I saw on traefik dashboard the rule is Host(blog-dev)

Desmond
  • 767
  • 1
  • 6
  • 18

3 Answers3

7

PathPrefix:/blog

When you have this as a routing rule, traefix won't automatically remove the prefix when sending to the container.

So unless you have a route /blog inside your container you will get a 404.

So what you normally do is also add a middleware to strip this -> https://docs.traefik.io/middlewares/stripprefix/

Also you appear not to be setting your rules based on your service.

So as an example for your first service blog,

try->

labels:
    - "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)"
    - "traefik.http.routers.blog.middlewares=strip-blog"
    - "traefik.http.middlewares.strip-blog.stripprefix.prefixes=/blog"

And then do the same for your other routes, don't forget to replace routers.blog with routers.docs etc..

Keith
  • 22,005
  • 2
  • 27
  • 44
  • Thanks. So this is not about the port using inside those containers? I have one without any prefix but it's still 404. – Desmond Nov 26 '19 at 16:27
  • @Desmond Yes because `traefik.frontend.rule` is incorrect.. Should be -> `traefik.http.routers.website.rule=` Can you see how `website` here maps with your service name?. – Keith Nov 26 '19 at 16:28
  • @Desmond Also just spotted how your defining your rule, just updated to how I think it should look.. eg. `Host('localhost') && PathPrefix('/blog')`, (note: those are back ticks, just can't do them in comments) and not `Host:localhost;PathPrefix:/blog` – Keith Nov 26 '19 at 16:43
  • @Keith If my application has static content(js,bootstrap etc) that is served on basis of folder name, the solution won't work as there would be no matching route for these. When these files would be accessed Traefik will again search for PathPrefix Blog. – Shubhanshu Rastogi Apr 13 '20 at 10:07
  • @Keith refer to the question here :https://stackoverflow.com/questions/61186640/cant-resolve-url-in-traefik-getting-error-404 – Shubhanshu Rastogi Apr 13 '20 at 11:13
6
labels: 
- traefik.http.services.<YOUR-SERVICE-NAME>.loadbalancer.server.port=9763

EG:

services:
  wso:
    image: "my-custom-wso-image"
    volumes:
      - .....
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wso.tls=true"
      - "traefik.http.routers.wso.rule=Host(`my.nice.url`)"
      - "traefik.http.services.wso.loadbalancer.server.port=9763" #<-----
Facty
  • 472
  • 4
  • 12
  • Thanks this worked for me in v3.6. By the way what is the job of loadbalancer by the way ? – Priyal Dec 08 '21 at 11:17
  • 1
    @Priyal Load-Balancers are used to to efficiently distributing incoming network traffic across multiple backend services. You can configure multiple URL's in your loadbalancer and traefik will automaticaly distribute the traffic. Example: https://github.com/swissbuechi/boilerplates/blob/main/docker-compose/traefik/config/service-example.yml provider: `file`: – swissbuechi Jan 11 '22 at 22:34
5

Thanks to @Keith I found the solution

version: '3'
services:
  website:
    build: ./website
    expose: [3000]
    networks: # It's essential to specify the same network in every service
      - webgateway
    labels:
      - "traefik.http.routers.website.rule=Host(`localhost`)" # Use the right format
      - "traefik.port=3000" # Let traefik find the right port
  blog:
    build: ./blog
    expose: [4000]
    networks:
      - webgateway
    labels:
      - "traefik.http.routers.blog.rule=Host(`localhost`) && PathPrefix(`/blog`)" # blog has a root as `/blog` so no need to strip otherwise too many redirects
      - "traefik.port=4000"
  docs:
    build: ./docs
    expose: [3000]
    networks:
      - webgateway
    labels:
      - "traefik.http.routers.docs.rule=Host(`localhost`) && PathPrefix(`/docs`)"
      - "traefik.http.routers.docs.middlewares=strip-docs" # Necessary as Keith mentioned
      - "traefik.http.middlewares.strip-docs.stripprefix.prefixes=/docs"
      - "traefik.port=3000"
  proxy:
    image: traefik
    command: --api.insecure=true --providers.docker
    networks:
      - webgateway
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

networks:
  webgateway:
    driver: bridge
Desmond
  • 767
  • 1
  • 6
  • 18