特雷菲克 addPrefix/replacePathRegex

Treafik addPrefix/replacePathRegex

我正在尝试使用 docker 设置地理服务器和 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/$

networks:
  web:

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

我也试过addPrefix,但也没用。

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

关于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/$"

连同以下引用

Regular expressions and replacements can be tested using online tools such as Go Playground or Regex101.

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

测试用例 1

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

测试用例 2

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

测试用例 3:geoserver 第 1 轮

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

测试用例 4:地理服务器第 2 轮

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

因为docker-compose$VARIABLE和[的形式提供了变量替换 =33=],则美元符号是 key word / reserved word,我们必须 转义 它并使我们在 [= 中使用美元符号 ($$) 36=]。请参阅 Whosebug and 了解更多信息。

边栏 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/$

编辑 1

测试用例 5:地理服务器第 3 轮

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

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

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

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

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

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

    • 替换:/geoserver/
    • 结果:/geoserver/path/to/api?key=value&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/$

原来问题出在我的 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: