Docker/400 错误请求上使用 HTTPS 的 Traefik 和 Nginx

Traefik and Nginx with HTTPS on Docker / 400 Bad Request

我正在尝试基于 Docker 使用 Traefik 和 Nginx 构建堆栈。没有HTTPS就万事大吉了,但是一配置HTTPS就报错

我在 example.com 上从 Nginx 收到此错误:400 错误请求/纯 HTTP 请求已发送到 HTTPS 端口。 在地址栏中我可以看到绿色的锁,上面写着连接是安全的。

Certbot 工作正常,所以我在正确的文件夹中有真正的 SSL 证书。

我可以在访问 traefik.example.com 时访问 Traefik 仪表板,但我必须接受无 SSL 浏览器警告,并且仪表板在没有 HTTPS 的情况下也能正常工作。

docker-compose.yml

version: '3.4'
services:
    traefik:
        image: traefik:latest
        ports:
            - "80:80"
            - "443:443"
            - "8080:8080"
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - ./traefik/traefik.toml:/etc/traefik/traefik.toml
            - ../letsencrypt:/etc/letsencrypt
        labels:
            - traefik.backend=traefik
            - traefik.frontend.rule=Host:traefik.example.com
            - traefik.port=8080
        networks:
           - traefik
    nginx:
        image: nginx:latest
        volumes:
            - ../www:/var/www
            - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
            - ../letsencrypt:/etc/letsencrypt
        labels:
            - traefik.backend=nginx
            - traefik.frontend.rule=Host:example.com
            - traefik.port=80
            - traefik.port=443
        networks:
            - traefik
networks:
    traefik:
        driver: overlay
        external: true
        attachable: true

traefik.toml

defaultEntryPoints = ["http", "https"]

[web]
    address = ":8080"

[entryPoints]
    [entryPoints.http]
        address = ":80"
        [entryPoints.http.redirect]
            entryPoint = "https"
    [entryPoints.https]
        address = ":443"
        [entryPoints.https.tls]
            [[entryPoints.https.tls.certificates]]
                certFile = "/etc/letsencrypt/live/example.com/fullchain.pem"
                keyFile = "/etc/letsencrypt/live/example.com/privkey.pem"

[docker]
    domain="example.com"
    watch = true
    exposedByDefault = true
    swarmMode = false

nginx.conf

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;

    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/public;
    index index.html;
}

感谢您的帮助。

首先不需要在Traefik和Nginx中都配置SSL重定向。此外,Traefik 前端仅匹配 non www 变体,但后端应用程序需要 www。最后,Traefik web 提供程序已弃用,因此应该有更新的 api 提供程序。

因为我刚刚偶然发现了 Traefik v2 的类似问题

400 Bad Request / The plain HTTP request was sent to HTTPS port

Nginx 错误日志显示

400 client sent plain HTTP request to HTTPS port while reading client request headers

百思不得其解,终于找到了错误的根源。并不是 TLS 证书无效或传输中的某些东西损坏了,而是路由器、服务和端口映射之间的连接断开了。

以前我没有看到 Docker Compose 堆栈有一个 Nginx 容器只监听 80/tcp。我假设一切正常,因为我将端口连接到 Traefik 负载均衡器,该负载均衡器连接到每个 http/https 具有单独路由器的端点的单独服务。这不知何故不起作用:

- "traefik.http.services.proxy.loadbalancer.server.port=80"
- "traefik.http.services.proxy-secure.loadbalancer.server.port=443"

中介 我现在打开 port: - "8008:80" - "8443:443" 并开始运行。进一步调查 Traefik 端口有什么问题,因为默认情况下应该得到 exposed。这不是解决方案,因为这些端口现在可供外界使用,但我将此解释留在这里,因为我找不到关于该主题的任何内容可以为我指明正确的方向,因此希望它对以后的其他人有所帮助.