如何使用 Traefik 2.0 和 Docker Compose 标签将 http 重定向到 https?

Posted

技术标签:

【中文标题】如何使用 Traefik 2.0 和 Docker Compose 标签将 http 重定向到 https?【英文标题】:How to redirect http to https with Traefik 2.0 and Docker Compose labels? 【发布时间】:2020-02-09 21:27:29 【问题描述】:

请注意,这是一个 Traefik V2 问题。我在 V1 上有一个解决方案,但 V2 是一个彻底的改造。

以上内容应该将http://whoami.mysite.com 重定向到https://whoami.mysite.com。

https 运行良好。 http 不会重定向到 https 并引发错误 404。

没有其他文件。目前所有内容都在这个 Docker-compose.yml 中,因为它是为进一步部署做准备的测试。

version: "3.3"

services:

  traefik:
    image: "traefik:v2.0"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web-secure.address=:443"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"
      #- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myhttpchallenge.acme.email=me@mail.com"
      - "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
    labels:
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.mysite.com`)"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.middlewares=redirect-to-https@docker"
      - "traefik.http.routers.whoami-secured.rule=Host(`whoami.mysite.com`)"
      - "traefik.http.routers.whoami-secured.entrypoints=web-secure"
      - "traefik.http.routers.whoami-secured.tls=true"
      - "traefik.http.routers.whoami-secured.tls.certresolver=myhttpchallenge"

【问题讨论】:

【参考方案1】:

好的,找到了...我假设中间件可以在 Traefik 级别声明,但这些必须在服务级别声明。

这一行:

- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

必须在 whoami 服务的标签中。

与所描述的问题无关的另一点是,http 质询必须在端口 80 上完成。

- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"

删除“网络安全”中的“安全”。

【讨论】:

这很奇怪。我在 Traefik 服务上声明了重定向中间件,并从应用服务中引用了它,它可以工作。 使用前面的代码,它似乎可以工作,但 http 实际上并没有重定向到 https。 如何从应用中引用中间件? 在 traefik 服务中,我有一个定义中间件的标签:traefik.http.middlewares.https-only.redirectscheme.scheme=https,在应用服务中我有一个标签:traefik.http.routers.myapp.rule=Host($APP_HOST)traefik.http.routers.myapp.entrypoints=webtraefik.http.routers.myapp.middlewares=https-only 我所有的东西都在标签里。据我了解,使用中间件需要两个标签:一个用于声明/配置(traefik.http.middlewares.https-only.redirectscheme.scheme=https),然后将其应用于服务(traefik.http.routers.myapp.middlewares =仅限https)。例如,声明可能位于应用程序服务或 treafik 服务中 - 就像我一样。请注意,即使您在应用服务中声明了中间件,您也会在仪表板中看到它以及在其他地方声明的其他中间件。也许我错了,但我认为您可以在任何服务中使用它们中的任何一个。【参考方案2】:

现在在 Gérald Croës 的教程中有一个可行的解决方案:

https://blog.containo.us/traefik-2-0-docker-101-fc2893944b9d

services:  
  traefik:  
    image: "traefik:v2.0.0"  
    # ...  
    labels:  
      # ...        
      # middleware redirect  
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"  
      # global redirect to https  
      - "traefik.http.routers.redirs.rule=hostregexp(`host:.+`)"  
      - "traefik.http.routers.redirs.entrypoints=web"  
      - "traefik.http.routers.redirs.middlewares=redirect-to-https"  

【讨论】:

这里是来自文章github.com/containous/blog-posts/blob/master/…的docker-compose.yml 请注意,现有的 acme.json 会阻止中间件重定向到 HTTPS。如果 Traefik 启动时已存在,则将其删除。【参考方案3】:

您不需要配置 Traefik 服务本身。在 Traefik 上,您只需要拥有 :443(网络安全)和 :80(网络)的入口点

因为 Traefik 只作为入口点,不会做重定向,所以目标服务上的中间件会做。

现在配置你的目标服务如下:

version: '2'
services:
  mywebserver:
    image: 'httpd:alpine'
    container_name: mywebserver
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.mywebserver-redirect-web-secure.redirectscheme.scheme=https
      - traefik.http.routers.mywebserver-web.middlewares=mywebserver-redirect-web-secure
      - traefik.http.routers.mywebserver-web.rule=Host(`sub.domain.com`)
      - traefik.http.routers.mywebserver-web.entrypoints=web
      - traefik.http.routers.mywebserver-web-secure.rule=Host(`sub.domain.com`)
      - traefik.http.routers.mywebserver-web-secure.tls.certresolver=mytlschallenge
      - traefik.http.routers.mywebserver-web-secure.tls=true
      - traefik.http.routers.mywebserver-web-secure.entrypoints=web-secure
      # if you have multiple ports exposed on the service, specify port in the web-secure service
      - traefik.http.services.mywebserver-web-secure.loadbalancer.server.port=9000

所以基本上流程是这样的:

请求:http://sub.domain.com:80 --> traefik(服务)--> mywebserver-web(路由器,http规则)--> mywebserver-redirect-web-secure(中间件,重定向到https)--> mywebserver-web -secure(路由器,https规则)--> mywebserver(服务)

【讨论】:

不确定这是要求。按照您描述的方式,请求似乎进入 traefik 端口 80,并且该方案在转发到后端服务之前更改为 https。但是后端服务不做 https 终止,所以会失败。想法是进行实际的 http 重定向,以便请求返回到端口 443 上的 traefik,从而保留主机。在 Traefik v1 中,可以通过静态配置轻松完成。 这行得通。这应该在文档中。您只需要为 http 版本制作一个路由器并将重定向中间件放在上面。 谢谢,为我工作。文档状态“如果您需要为 HTTP 和 HTTPS 请求定义相同的路由,则需要定义两个不同的路由器:一个带有 tls 部分,一个没有。”所以这是有道理的。如果您没有为端口 80 定义路由,则重定向将不起作用。此处的文档:doc.traefik.io/traefik/v2.2/routing/routers/#tls【参考方案4】:

当我在寻找如何通过 Traefik v2.2 将所有内容重定向到 HTTPS 时,我正在寻找这个答案,对我来说最好的选择是将此 ENV 变量添加到 Traefik,它会自动将所有流量重定向到 HTTPS。

TRAEFIK_ENTRYPOINTS_WEB_ADDRESS=:80
TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS=:443
TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_TO=websecure

有了这个,我不需要向中间件添加任何东西。有关该功能的更多信息,请访问official documentation。

【讨论】:

谢谢,这就是我要找的。我没有使用 ENV 变量,只是在静态配置中添加了一些行:``` [entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http] [entryPoints.web.http.redirections] [entryPoints.web.http.redirections.entryPoint] to = "websecure" 方案 = "https" [entryPoints.websecure] 地址 = ":443" ``【参考方案5】:

我建议在这里查看文档Entrypoint redirect 80 > 443

这对我有用,如果您希望所有流量从端口 80 重定向到 443,这是最好的解决方案。

--entrypoints.web.address=:80
--entrypoints.web.http.redirections.entryPoint.to=websecure
--entrypoints.web.http.redirections.entryPoint.scheme=https
--entrypoints.web.http.redirections.entrypoint.permanent=true
--entrypoints.websecure.address=:443

注意:

周围有很多例子。看看websecure。

有时它写成网络安全。

希望对您有所帮助;o)

【讨论】:

只是在这里寻求澄清 - 这为所有服务重定向所有流量,并消除了在服务级别声明的重定向中间件的需要?假设,我这样做了,然后我有 5 个服务中的一个,我希望通过纯 http 访问,所以这里没有重定向。那么我可以“跳过”单个服务的重定向吗? @ChristianW 好问题;你应该尝试一下 :) 我想它不会起作用,因为它是一个全局重定向。 如果这个解决方案对你不起作用,导致 Traefik 容器本身没有开始给出错误:command traefik error: failed to decode configuration from flags: field not found, node: http 尝试将 Traefik 版本更新到最新的可用版本(和我一起 v2.0 给出了错误,但 v2.3 现在 一切正常)【参考方案6】:

似乎全局设置不是通过标签完成的,而是通过 traefik 命令参数完成的。您的问题是关于标签的,但也许这个解决方案也适用于您?

这里是做什么,根据官方文档:https://docs.traefik.io/migration/v1-to-v2/#http-to-https-redirection-is-now-configured-on-routers

v1 中的内容:

# static configuration
defaultEntryPoints = ["web", "websecure"]

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.redirect]
      entryPoint = "websecure"

  [entryPoints.websecure]
    address = ":443"
    [entryPoints.websecure.tls]

现在看来是:

--entrypoints.web.address=:80
--entrypoints.web.http.redirections.entrypoint.to=websecure
--entrypoints.web.http.redirections.entrypoint.scheme=https
--entrypoints.websecure.address=:443
--providers.docker=true

【讨论】:

【参考方案7】:

对于使用最新版本 traefik 的 kubernetes helm chart 用户,您可以在 traefik 值文件中使用它(在图表版本 10.3.2 / traefik 2.5 上测试)将所有流量重定向到 httpS

# values.yaml
ports:
  web:
    redirectTo: websecure

如果您需要 CRD 更新(traefik 2.4 -> 2.5),请使用 gist

【讨论】:

【参考方案8】:

您只需将以下内容添加到 traefik 配置中,而不是应用程序;

- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"

这是 traefik 的完整 yaml 配置

version: "3.3"

services:

  traefik:
    image: "traefik:v2.5"
    container_name: "traefik"
    command:
      # - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=user@domain.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"

    ports:
      - "443:443"
      - "80:80"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

示例应用程序

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`subdomain.domain.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"

【讨论】:

以上是关于如何使用 Traefik 2.0 和 Docker Compose 标签将 http 重定向到 https?的主要内容,如果未能解决你的问题,请参考以下文章

Traefik 2.0闸道超时

使用 Eureka 和 traefik 和 docker compose 的微服务服务发现

使用 docker-compose 和 traefik 实现微服务之间的通信

traefik 2.1 for docker

traefik 代理后面的 docker 中的 gitlab 失败(通常)

Traefik无法通过docker-compose连接到服务器。