Traefik docker 配置重写的基于路径的路由

Traefik docker config path-based routing with rewriting

2 天大的 traefik 新手,需要帮助了解 istm 是什么是基本的 docker traefik v2 中的提供程序配置...

我试过搜索文档,但就是想不通如何做我想做的事。

我想要 docker 个像

这样的容器

并通过 traefik 通过 urls 访问这些

但是应用程序本身不喜欢这些额外的路径,所以我想从访问路径中删除前缀,这样应用程序就看不到它们。

如果我访问 http://app.mydomain.com/app2/foo 我希望容器 app2 获得请求 http://{container.ip.addr}}/foo

作为重现,我知道部分有效的配置在我的 traefik docker-compose.yml:

version: "3"
services:
  traefik:
    image: "traefik:v2.5.4"
    command:
      - --entrypoints.web.address=:80
      - --providers.docker=true
      - --api
      - --api.insecure=true
      - --api.dashboard=true
      - --providers.file.directory=/etc/traefik/dynamic
      - --providers.docker.defaultRule=Host(`app.mydomain.com`) && PathPrefix(`/{{ index .Labels "com.docker.compose.service" }}`)
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  app1:
    image: containous/whoami:v1.3.0
  app2:
    image: containous/whoami:v1.3.0
  app3:
    image: containous/whoami:v1.3.0

127.0.0.1 app.mydomain.com 添加到 \etc\hosts 后,对 http://app.mydomain.com/app{1,2,3}/foo 进行卷曲,这会路由到正确的服务,但他们收到的请求路径是 /app1/foo/app2/foo, /app3/foo 而我希望他们都得到 /foo.

我觉得我希望能够将以下内容添加到 docker-compose 中的命令行参数中:

--providers.docker.middleware.default-stripprefix.stripprefix.prefixes=`/{{ index .Labels "com.docker.compose.service" }}`

但它不起作用(错误:command traefik error: failed to decode configuration from flags: field not found, node: middleware

我找不到任何说明正确的命令行参数可能是什么的文档。

我认为它可能需要在一个动态配置文件中(我已经看到 tls 配置太混乱了,但我想在这个阶段将所有这些都排除在重现之外!)但还是不能'似乎找不到默认中间件的正确配置。

我可以找到很多引用(并让它工作),我必须在每个容器的标签中指定它,但我更愿意使用 traefik 配置本身中的一次性条目将其默认。

我已经为此苦恼了 2 天了。我试过搜索文档站点、这个社区和 googleverse,但没有成功。对我来说,这似乎是一个“101”配置! :-)

请有人帮助我,不仅可以解决我的问题,还可以选择性地教我如何在文档站点中找到自己的解决方案。我已经看到很多人提到文档站点很好,但对我来说,对于 v2,它们似乎很少。

好的,所以我会 post 我给出的答案,以防有人找到并想知道。

中间件需要在 Traefik dynamic 配置文件中定义。

这可以在 static 配置文件的端点规范中引用。

一旦我需要一个单独的文件用于动态配置,我决定也为静态配置使用一个文件而不是命令行参数。

所以 3 文件的解决方案是:

docker-compose.yml

version: "3"
services:
  traefik:
    image: "traefik:v2.5.4"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "{path}/traefik.yml:/etc/traefik/traefik.yml:ro"
      - "{path}/dynamic.yml:/etc/traefik/dynamic.yml:ro"

  app1:
    image: containous/whoami:v1.3.0
  app2:
    image: containous/whoami:v1.3.0
  app3:
    image: containous/whoami:v1.3.0

traefik.yml

api:
  insecure: true
  dashboard: true
providers:
  docker:
    defaultRule: "Host(`app.mydomain.com`) && PathPrefix(`/{{ index .Labels \"com.docker.compose.service\" }}`)"
  file:
    filename: "/etc/traefik/dynamic.yml"
entrypoints:
  web:
    address: ":80"
    http:
      middlewares:
        - root-stripprefix@file

dynamic.yml

http:
  middlewares:
    root-stripprefix:
      stripPrefixRegex:
        regex:
          - "/[^/]+"

动态配置指定了一个 StripPrefix 中间件 - 我实际上使用了 StripPrefixRegex 来抓取路径第一部分中的任何内容,而无需指定它。

此中间件随后与 Web 端点相关联,因此适用于使用它的所有内容。

这相当简单地解决了这个问题,但在能够到达那里之前,这是一个了解 Traefik 文档和配置系统的旅程。如果需要更多详细信息,我已经在 this post 中更详细地描述了旅程。

关于真实世界容器间连接的额外说明...

另请注意,在一个更真实的示例中,使用单独的 docker-compose 文件,有必要通过向每个 docker-编写文件如:

service:
  app1:
...
    networks:
      - proxy
networks:
  proxy:
    external: true
    name: proxy

第一次使用一次性命令创建网络后 docker network create proxy

我再次更详细地写了关于这个的想法 - 请参阅 this post

希望这能帮助别人至少节省一些我为此花费的时间。