【问题标题】:Traefik 'PathPrefix' is not working as expected for underlying requestsTraefik 'PathPrefix' 对于底层请求没有按预期工作
【发布时间】:2020-05-22 02:37:10
【问题描述】:

尝试在 Traefik 中实现简单的 Nginx 请求路由。 不幸的是,Traefik 的 PathPrefix 无法开箱即用

location /app1/ {
    proxy_bind $server_addr;
    proxy_pass http://my-subdomain.localhost/app1/;
}

location /app2/ {
    proxy_bind $server_addr;
    proxy_pass http://my-subdomain.localhost/app2/;
}

location /app3/ {
    proxy_bind $server_addr;
    proxy_pass http://my-subdomain.localhost/app3/;
}

使用 docker-compose 旋转所有服务的 Traefik 配置代码。

文件:dockercompose.yml

version: '3.3'

services:

  traefik-reverse-proxy:
    container_name: traefik-reverse-proxy
    image: traefik:v2.2
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.reverse-proxy.rule=Host(`my-subdomain.localhost`) && PathPrefix(`/traefik`)"
      - "traefik.http.routers.reverse-proxy.service=api@internal"

  app1:
    container_name: app1
    image: registry.gitlab.com/my-hobby-project/app1:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app1.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app1`))"
    
  app2:
    container_name: app2
    image: registry.gitlab.com/my-hobby-project/app2:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app2.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app2/`))"

  app3:
    container_name: app3
    image: registry.gitlab.com/my-hobby-project/app3:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app3.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app3`))"

提示:

A. App3 是我的 Angular 应用程序,在这种情况下,我实际上可以访问 index.html 页面,但底层资源正在获取 404。

第一个请求:http://staging.localhost/app3 -> 找到 index.html。

以下请求:例如http://staging.localhost/assests/util.js -> 404(我希望traefik应该将此请求作为http://staging.localhost/app3/assests/util.js

我也尝试使用AddPrefix,但没有成功。

添加前缀代码:

 - "traefik.http.routers.app3.rule=Host(`staging.localhost`) && (PathPrefix(`/app3`))"
 - "traefik.http.middlewares.add-app3.addprefix.prefix=/app3"
 - "traefik.http.routers.app3.middlewares=add-app3"

B.还尝试在 pathPrefix 末尾使用斜杠(检查上面的 app2 示例代码),不幸的是,它也不起作用。

C.使用 Traefik 2.2 版(参见 docker-compose.yml 文件)

问题:

  1. 如何使用子域和路径前缀(即http://my-subdomain.localhost/traefik)访问 traefik 仪表板
  2. 如何访问 Angular 的底层资源:http://my-subdomain.localhost/app3`

【问题讨论】:

标签: docker docker-compose reverse-proxy traefik


【解决方案1】:

我也面临同样的困难。使用像 whoami 这样的容器,没问题。但是对于像 nginx 这样的容器,您需要“/nginx”才能对容器有意义,正如 Zespri 在PathPrefix and strip discussion 中所解释的那样。 这是一个 docker-compose.yml 来说明我的观点。

注意主机和 nginx1 容器之间共享的卷。

version: "3.3"

services:

  traefik:
    image: "traefik:v2.1"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/traefik.yml:ro"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"

  whoami1:
    image: containous/whoami:v1.5.0
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami1.entrypoints=http"
      - "traefik.http.routers.whoami1.rule=Host(`myhost.mydomain.org`) && PathPrefix(`/whoami`)"


  whoami2:
    image: containous/whoami:v1.5.0
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami2.entrypoints=http"
      - "traefik.http.routers.whoami2.rule=Host(`whoami.mydomain.org`)"

  nginx1:
    image: nginx:latest
    volumes:
      - ./html:/usr/share/nginx/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx1.entrypoints=http"
      - "traefik.http.routers.nginx1.rule=Host(`myhost.mydomain.org`) && PathPrefix(`/nginx`)"

 nginx2:
    image: nginx:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx2.entrypoints=http"
      - "traefik.http.routers.nginx2.rule=Host(`nginx.mydomain.org`)"

主机的 html 文件夹包含一个 nginx 文件夹,它将响应“/nginx”。

$ tree html/
html/
└── nginx
    └── index.html

如果不做这个host和container之间的共享,会报如下错误。

$ docker logs traefik_nginx1_1
2021/02/16 13:36:16 [error] 27#27: *1 "/usr/share/nginx/html/nginx/index.html" is not found (2: No such file or directory), client: 172.24.0.3, server: localhost, request: "HEAD /nginx/ HTTP/1.1", host: "mydomain.org"

这样,4个查询都答对了!

curl -Ik http://myhost.mydomain.org/whoami
HTTP/1.1 200 OK

curl -Ik http://whoami.mydomain.org
HTTP/1.1 200 OK

curl -Ik http://myhost.mydomain.org/nginx
HTTP/1.1 200 OK

curl -Ik http://nginx.mydomain.org
HTTP/1.1 200 OK

【讨论】:

    【解决方案2】:

    您在配置中遇到的问题是您多次覆盖相同的app1 路由器。它认为这就是为什么只有一条路线有效的原因。

    基本上不是这样做:

      app1:
        container_name: app1
        image: registry.gitlab.com/my-hobby-project/app1:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app1.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app1`))"
    
      app2:
        container_name: app2
        image: registry.gitlab.com/my-hobby-project/app2:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app1.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app2/`))"
    
      app3:
        container_name: app3
        image: registry.gitlab.com/my-hobby-project/app3:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app1.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app3`))"
    

    你应该这样做

      app1:
        container_name: app1
        image: registry.gitlab.com/my-hobby-project/app1:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app1.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app1`))"
    
      app2:
        container_name: app2
        image: registry.gitlab.com/my-hobby-project/app2:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app2.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app2/`))"
    
      app3:
        container_name: app3
        image: registry.gitlab.com/my-hobby-project/app3:latest
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app3.rule=(Host(`my-subdomain.localhost`) && PathPrefix(`/app3`))"
    

    另请注意,(Host(`my-subdomain.localhost`) && PathPrefix(`/app3`)) 周围不需要括号。你可以简单地做Host(`my-subdomain.localhost`) && PathPrefix(`/app3`)

    我基本上感觉到了同样的陷阱,Traefik 不会轻易显示错误。它基本上只是默默地失败了...... 下次,启用调试并在日志中查找错误。我在这篇文章中展示了如何做到这一点:https://juliensalinas.com/en/traefik-reverse-proxy-docker-compose-docker-swarm-nlpcloud/

    希望它能解决您的问题!

    【讨论】:

    • 对我不起作用。
    猜你喜欢
    • 1970-01-01
    • 2021-04-07
    • 2021-11-09
    • 2015-04-11
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    相关资源
    最近更新 更多