【问题标题】:Getting 502 Bad Gateway when trying to configure HTTPS on Traefik尝试在 Traefik 上配置 HTTPS 时出现 502 Bad Gateway
【发布时间】:2020-09-07 01:34:55
【问题描述】:

我有一个基本的 Traefik 2 设置,适用于 HTTP here...

现在我正在尝试让 HTTPS 正常工作,并使用 TLS 和重定向对仪表板进行基本身份验证...

docker_compose.yml

version: '3.8'
networks:
  myweb:
    external: true

services:
  proxy:
    image: traefik:v2.3.0-rc4-windowsservercore-1809
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      # Mount the certs drive
      - ./traefik-ssl-certs/:c:/certs/
      # Mount the config folder
      - ./traefik-config/:c:/config/
      # Mount the host docker engine pipe ("docker volume ls")
      - source: '\\.\pipe\docker_engine'
        target: '\\.\pipe\docker_engine'
        type: npipe
    command:
      - "--api.insecure=true"

      # Register the traefik config directory as per: https://docs.traefik.io/providers/file/#directory
      - --providers.file.directory=c:/config/
      - --providers.file.watch=true

      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443

      # Redirect http to https
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.web.http.redirections.entryPoint.scheme=https
      - --entrypoints.web.http.redirections.entrypoint.permanent=true

      # Configure Docker provider
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.endpoint=npipe:////./pipe/docker_engine"
      - "--providers.docker.network=myweb"
      - "--providers.docker.watch=true"
    networks:
      - myweb
    labels:
      - traefik.http.routers.api.service=api@internal
      - traefik.enable=true
      - traefik.docker.network=myweb

      
  remoteling:
    image: remoteling:latest
    container_name: remoteling
    networks:
      - myweb
    labels:
      - traefik.enable=true
      - traefik.docker.network=myweb

      - traefik.http.middlewares.http2https.redirectscheme.scheme=https
      - traefik.http.routers.remoteling-http.middlewares=http2https
      - traefik.http.routers.remoteling-http.rule=Host(`example.com`) || Host(`example.example.com`)
      - traefik.http.routers.remoteling-http.entrypoints=web
      
      - traefik.http.services.remoteling.loadbalancer.server.port=443
      - traefik.http.routers.remoteling-https.rule=Host(`example.com`) || Host(`example.example.com`)
      - traefik.http.routers.remoteling-https.entrypoints=websecure
      - traefik.http.routers.remoteling-https.tls=true
    depends_on:
      - proxy

我正在从 powershell 运行:

docker network create -d nat myweb
docker-compose -p myweb up 

在我的工作目录中,我有以下文件结构:

  • ./docker-compose.yml
  • ./traefik-config/traefik.yml
  • ./traefik-ssl-certs/example.com.crt
  • ./traefik-ssl-certs/example.com.key
  • ./traefik-ssl-certs/example.example.com.key
  • ./traefik-ssl-certs/example.example.com.key

traefik.yml 文件如下所示:

tls:
  certificates:
    - certFile: c:/certs/example.example.com.crt
      keyFile: c:/certs/example.example.com.key
    - certFile: c:/certs/example.com.crt
      keyFile: c:/certs/example.com.key

traefik 仪表板显示我的服务定义为负载均衡器,这很好(除了负载均衡器之外还有其他类型的服务吗?我不确定除了通过负载均衡器之外如何定义端口)。单击该服务会为我提供本地网络 IP - 当我访问该 IP 时,我的网站加载正常(尽管会出现 SSL 证书不匹配警告 - 预期)。

但是,当我尝试访问 https://example.comhttps://example.example.com - 我得到一个 502 Bad Gateway。知道为什么我会得到这个吗?

浏览器显示 SSL 证书有效,没有警告,所以我认为我的证书配置没问题。

http 到 https 的重定向似乎有效,如果我访问 http://example.com,它会将我转发到 https://example.com

我的路由配置有什么问题导致这些错误网关?

【问题讨论】:

    标签: docker ssl traefik


    【解决方案1】:

    我已经解决了我的问题!有几个问题:

    1. 我已经在我的 Dockerfile 中配置了一个 TLS 证书,这是从我在服务器上将映像作为单个服务运行时开始的。所以我的图像已经有端口 443 与 TLS 证书绑定。我认为当 Traefik 路由器尝试为服务配置 TLS 时,这会导致问题。所以我不得不重建我的形象,删除 TLS。我还删除了需要 HTTPS 属性的代码,现在由 traefik 负责。

    图像只需要暴露 1 个端口:我现在的理解是我的 web 应用程序应该通过端口 80 运行(例如,甚至不需要暴露端口 443镜像的防火墙)和 Traefik 路由器通过端口 80 配置和处理 TLS/443 等。

    1. 我实际上并没有正确定义我的 HTTP 和 HTTPS 服务。我在下面分享了我的 docker-compose.yml 文件 - 注意 traefik 和我的其他服务我已将标签分成几个部分:定义服务、HTTP 路由、HTTPS 路由、重定向中间件和 traefik 仪表板的基本身份验证.我找不到任何好的文档或教程来真正分解 traefik 2.0 的必要方面并明确分类。

    服务定义标签/负载均衡器端口应指向托管图像服务的任何端口,例如大多数情况下端口为 80,或者在 traefik 服务的情况下为 8080。但至关重要的是,它不需要指向 https 的 443。

    总之,我的(详细)学习笔记毕竟是,你需要:

    • 再次将服务定义为标签:没有服务定义标签对我不起作用。我必须添加一个服务标签,指向定义图像的服务名称。
    • 为 http 和 https 定义路由器:无论您在 traefik.http.routers.YOUR_ROUTER_NAME 之后放置什么文本,都将成为您的路由器。我不清楚我需要为 http 和 https 使用单独的路由器。您必须为每项服务(例如 traefik、whoami、remoteling 等)执行此操作
    • 定义路由器的入口点:AFAIK 您在 traefik 命令中的入口点之后放置的名称定义了一个新的入口点,您可以将其用于其他服务。因此,在 traefik 服务定义中,您将拥有 --entrypoints.WEBNAME.address=:80 和 --entrypoints.WEBSECURENAME.address=:443 (将这些大写替换为您自己的名称以在整个 docker-compose.yml 文件中使用。
    • 定义要捕获的路由器域名:就像您为每个 http 和 https 定义路由器一样,您必须为这两个路由器定义要捕获的域,即使只是相同的域/路径。
    • 为 https 路由器添加 tls:对于 https 路由器,您需要 tls.true 标签。
    • 为 traefik 和您的每个服务单独的中间件重定向定义:我读过您可以声明一个全局的,但是 AFAIK 每个服务必须通过将中间件分配给 http 路由器来选择加入。李>
    • 在 Docker for Windows 上提供自己的 SSL 证书:关于使用自己的 SSL 证书运行 Docker for Windows 的信息很少。我的“traefik”工作目录中有一个批处理脚本,其中包含一个包含 SSL 证书(crt 和密钥文件)的子文件夹。我将它作为第一卷安装,- ./traefik-ssl-certs/:c:/certs/。然后,在我的工作目录中,我有另一个名为 traefik-config 的文件夹,其中包含我的 traefik.yml 文件(上述问题中的详细信息)。在 linux 中似乎每个人都只是直接挂载配置文件,但是在 Windows 中挂载文件不起作用,所以我不得不挂载为文件夹,然后我使用了命令 providers.file.directory=c:/config/,它告诉 traefik 查找配置文件那里。配置文件提供了 SSL 证书的位置以供 traefik 加载。如果您为路由器启用 TLS,Traefik 将自动使用与您在该路由器上指定的域匹配的任何证书。
    • Basic Auth:必须将中间件定义为一个标签,然后将该中间件分配给您的 https 路由器。而且我想如果您不使用 HTTPS 重定向,那么您可以将其分配给您的 http 路由器,但它显然不安全。

    docker-compose.yml:

    version: '3.8'
    networks:
      myweb:
        external: true
    
    services:
      proxy:
        image: traefik:v2.3.0-rc4-windowsservercore-1809
        container_name: traefik
        ports:
          - "80:80"
          - "443:443"
          - "8080:8080"
        volumes:
          # Mount the certs drive
          - ./traefik-ssl-certs/:c:/certs/
          # Mount the config folder
          - ./traefik-config/:c:/config/
          # Mount the host docker engine pipe ("docker volume ls")
          - source: '\\.\pipe\docker_engine'
            target: '\\.\pipe\docker_engine'
            type: npipe
        command:
          - --api=true
          - --api.dashboard=true
          - --api.insecure=false
    
          # Register the traefik config directory as per: https://docs.traefik.io/providers/file/#directory
          - --providers.file.directory=c:/config/
          - --providers.file.watch=true
    
          - --entrypoints.web.address=:80
          - --entrypoints.websecure.address=:443
    
          # Configure Docker provider
          - --providers.docker=true
          - --providers.docker.exposedbydefault=false
          - --providers.docker.endpoint=npipe:////./pipe/docker_engine
          - --providers.docker.network=myweb
          - --providers.docker.watch=true
        networks:
          - myweb
        labels:
          - traefik.enable=true
          - traefik.docker.network=myweb
    
          # Define the service
          - traefik.http.services.proxy.loadbalancer.server.port=8080
    
          # Routing for dashboard HTTP
          - traefik.http.routers.dash-http.service=api@internal
          - traefik.http.routers.dash-http.rule=Host(`example.com`)
          - traefik.http.routers.dash-http.entrypoints=web
    
          # Routing for dashboard HTTPS
          - traefik.http.routers.dash-https.service=api@internal
          - traefik.http.routers.dash-https.rule=Host(`example.com`)
          - traefik.http.routers.dash-https.entrypoints=websecure
          - traefik.http.routers.dash-https.tls=true
    
          # Http-to-Https redirect Middleware
          - traefik.http.middlewares.dash-http2https.redirectscheme.scheme=https
          - traefik.http.middlewares.dash-http2https.redirectscheme.permanent=true
          - traefik.http.routers.dash-http.middlewares=dash-http2https
    
          # BasicAuth for dashboard
          # Windows doesn't have htpasswd command so I generated one here: https://hostingcanada.org/htpasswd-generator/
          # As per Traefik documentation, escaped single $ char with $$ for the yml parser
          # user/pass = admin/testpassword 
          - traefik.http.middlewares.api-auth.basicauth.users=admin:$$2y$$10$$mfWQ11K16V6gVK.8Y6q1Eeh765NZscmjCrjJlAtaWubEsjU8HLYOO
          - traefik.http.routers.dash-https.middlewares=api-auth
    
      remoteling:
        image: remoteling:latest
        container_name: remoteling
        networks:
          - myweb
        labels:
          - traefik.enable=true
          - traefik.docker.network=myweb
    
          # Define the service
          - traefik.http.services.remoteling.loadbalancer.server.port=80
    
          # Routing for remoteling HTTP
          - traefik.http.routers.remoteling-http.service=remoteling
          - traefik.http.routers.remoteling-http.entrypoints=web
          - traefik.http.routers.remoteling-http.rule=Host(`services.example.com`) 
    
          # Routing for remoteling HTTPS
          - traefik.http.routers.remoteling-https.service=remoteling
          - traefik.http.routers.remoteling-https.entrypoints=websecure
          - traefik.http.routers.remoteling-https.rule=Host(`services.example.com`)
          - traefik.http.routers.remoteling-https.tls=true
          
          # Http-to-Https redirect Middleware
          - traefik.http.middlewares.remoteling-http2https.redirectscheme.scheme=https
          - traefik.http.middlewares.remoteling-http2https.redirectscheme.permanent=true
          - traefik.http.routers.remoteling-http.middlewares=remoteling-http2https
        depends_on:
          - proxy
    

    希望其他人觉得这很有用。

    【讨论】:

    • 谢谢!!我花了一整天的时间试图弄清楚这一点——我认为redirectscheme 代码而不是端口代理是成功的。
    猜你喜欢
    • 2016-01-04
    • 2018-10-30
    • 2017-09-01
    • 2015-11-02
    • 2018-08-09
    • 2014-04-30
    • 1970-01-01
    • 2018-04-23
    • 2016-04-20
    相关资源
    最近更新 更多