【问题标题】:Treafik addPrefix/replacePathRegexTraefik 添加前缀/replacePathRegex
【发布时间】:2021-08-20 20:17:03
【问题描述】:

我正在尝试使用 docker 设置 geoserver 和 traefik,但路径有问题。

Geoserver 的主要入口点位于 /geoserver,但我想让它可以在我的域的根路径访问,比如说 example.com。这是我整理的docker-compose 文件:

version: "3"

services:
  traefik:
    image: traefik:2.4
    restart: unless-stopped
    networks:
      - web
    ports:
      - 80:80
      - 443:443
    command:
      - --log.level=DEBUG
      - --providers=docker
      - --providers.docker.network=geoserver_web
      - --entrypoints.websecure.address=:443
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=websecure
      # - --api.dashboard=true
      - --certificatesresolvers.lets-encrypt.acme.email=admin@example.com
      - --certificatesresolvers.lets-encrypt.acme.storage=acme.json
      - --certificatesresolvers.lets-encrypt.acme.tlschallenge=true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
  
  geoserver:
    image: oscarfonts/geoserver:latest
    restart: unless-stopped
    networks:
      - web
    labels:
      - traefik.port=8080
      - traefik.http.routers.geoserver.rule=Host(`example.com`)
      - traefik.http.routers.geoserver.entrypoints=websecure
      - traefik.http.routers.geoserver.tls=true
      - traefik.http.routers.geoserver.tls.certresolver=lets-encrypt
      - traefik.http.middlewares.geoserver.replacepathregex.regex=(.*)
      - traefik.http.middlewares.geoserver.replacepathregex.replacement=/geoserver/$$1

networks:
  web:

在通过traefik docs 之后,我认为在地理服务器服务上使用replacepathregex 应该将/geoserver 添加到传递给地理服务器的所有请求的路径中,并且应该使服务在example.com 可用,而不是@987654330 @,但它不起作用。

我也试过addPrefix,但也没有用。

我的配置不正确吗? 或者我对这些中间件做什么的理解? 有没有办法将我的服务配置为可通过example.com 访问,而不是example.com/geoserver

【问题讨论】:

    标签: docker docker-compose traefik


    【解决方案1】:

    关于ReplacePathRegex: Configuration Examples,Docker 选项卡,它提到如下示例:-

    # Replace path with regex
    labels:
      - "traefik.http.middlewares.test-replacepathregex.replacepathregex.regex=^/foo/(.*)"
      - "traefik.http.middlewares.test-replacepathregex.replacepathregex.replacement=/bar/$$1"
    

    连同以下引述

    正则表达式和替换可以使用Go PlaygroundRegex101等在线工具进行测试。

    我使用Regex101测试并确保上面的示例配置并扩展,以便我们实现以下场景的要求。

    测试用例 1

    • 正则表达式:/foo/(.*)(注意:此处没有前导插入符号^
    • 测试字符串:https://my.domain.com/foo/api
    • 代入:/bar/$1(注:这里有单美元唱$,稍后解释)
    • 结果:https://my.domain.com/bar/api

    测试用例 2

    • 正则表达式:/foo/(.*)
    • 测试字符串:https://my.domain.com/foo/api
    • 替换:/$1
    • 结果:https://my.domain.com/api

    测试用例 3:geoserver 第一轮

    • 正则表达式:(.*)/(.*)
    • 测试字符串:https://my.domain.com/api
    • 替换:$1/geoserver/$2
    • 结果:https://my.domain.com/geoserver/api

    测试用例 4:geoserver 第 2 轮

    • 正则表达式:(.*)/(.*)
    • 测试字符串:https://my.domain.com/api
    • 替换:/geoserver/$2
    • 结果:/geoserver/api
    边栏1:为什么我们需要双美元唱($$)?

    因为 docker-compose 提供了变量替换,形式为$VARIABLE${VARIABLE},所以美元符号是key word / reserved word,我们必须转义它并导致我们在docker-compose.yml 中使用美元唱($$)。请参阅 StackOverflow QuestionAnswer 了解更多信息。

    边栏 2:前导插入符号 (^)

    经过一段时间的反复试验,我意识到有一点不同,因为 Traefik 需要前导插入符,而 Regex101 不需要。直到现在,我仍然不知道为什么会这样并且记得那样:D

    总结

    按照测试用例4实现我们的要求,docker-compose label应该如下例

    labels:
      - traefik.http.middlewares.geoserver.replacepathregex.regex=^(.*)/(.*) # <-- the leading caret
      - traefik.http.middlewares.geoserver.replacepathregex.replacement=/geoserver/$$2
    

    编辑 1

    测试用例 5:geoserver 第三轮

    • 正则表达式:^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?/(.*)$

    • 测试字符串:https://my.domain.com/path

      • 替换:/geoserver/$4
      • 结果:/geoserver/path
    • 测试字符串:https://my.domain.com/path/to

      • 替换:/geoserver/$4
      • 结果:/geoserver/path/to
    • 测试字符串:https://my.domain.com/path/to/api

      • 替换:/geoserver/$4
      • 结果:/geoserver/path/to/api
    • 测试字符串:https://my.domain.com/path/to/api?key=value

      • 替换:/geoserver/$4
      • 结果:/geoserver/path/to/api?key=value
    • 测试字符串:https://my.domain.com/path/to/api?key=value&amp;anotherkey=anothervalue

      • 替换:/geoserver/$4
      • 结果:/geoserver/path/to/api?key=value&amp;anotherkey=anothervalue

    总结

    按照测试用例5实现我们的要求,docker-compose label应该如下例

    labels:
      - traefik.http.middlewares.geoserver.replacepathregex.regex=^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?/(.*)$$ # <-- the leading caret and double dollar sign at the end
      - traefik.http.middlewares.geoserver.replacepathregex.replacement=/geoserver/$$4
    

    【讨论】:

    • 谢谢,@charlee-chitsuk,但您的回答无效。最后建议的模式,即(.*)(.*),捕获最后一个斜线之前的所有内容,然后在替换模式中,您将删除它之前的所有内容(第一个捕获组)并用/geoserver替换它,但这不是目标(它也没有像答案中描述的那样工作)。目标是将/geoserver 添加到我们传递给geoserver 服务的任何请求中。
    • 请看我的编辑1,测试用例5。
    • 我在这方面花了更多时间,结果发现问题不是正则表达式或replacepathregexaddprefix 中间件的语法,而是将它们附加到地理服务器路由器。请参阅我自己的答案以获取更新的docker-compose.yml
    【解决方案2】:

    原来问题是我的 traefik 配置!我需要将中间件添加到地理服务器路由器。这是更新后的docker-compose.yml(我选择了addprefix,而不是replacepathregex,因为后者太过分了):

    version: "3"
    
    services:
      traefik:
        image: traefik:2.4
        restart: unless-stopped
        networks:
          - web
        ports:
          - 80:80
          - 443:443
        command:
          - --log.level=DEBUG
          - --providers=docker
          - --providers.docker.network=geoserver_web
          - --entrypoints.websecure.address=:443
          - --entrypoints.web.address=:80
          - --entrypoints.web.http.redirections.entrypoint.to=websecure
          - --entrypoints.web.http.redirections.entrypoint.scheme=websecure
          # - --api.dashboard=true
          - --certificatesresolvers.lets-encrypt.acme.email=admin@example.com
          - --certificatesresolvers.lets-encrypt.acme.storage=acme.json
          - --certificatesresolvers.lets-encrypt.acme.tlschallenge=true
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock:ro
          - ./letsencrypt:/letsencrypt
      
      geoserver:
        image: oscarfonts/geoserver:latest
        restart: unless-stopped
        networks:
          - web
        labels:
          - traefik.http.middlewares.add-geoserver-prefix.addprefix.prefix=/geoserver
          - traefik.port=8080
          - traefik.http.routers.geoserver.rule=Host(`example.com`)
          - traefik.http.routers.geoserver.entrypoints=websecure
          - traefik.http.routers.geoserver.tls=true
          - traefik.http.routers.geoserver.tls.certresolver=lets-encrypt
          - traefik.http.routers.geoserver.middlewares=add-geoserver-prefix@docker
    
    networks:
      web:
    

    【讨论】:

      猜你喜欢
      • 2022-11-17
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 2020-06-15
      • 2012-04-03
      • 1970-01-01
      • 2014-09-29
      相关资源
      最近更新 更多