求助:同一Docker容器通过Traefik配置HTTPS与WSS同域名访问
解决方案
核心问题分析
- Traefik未暴露WSS入口端口:你在
traefik.toml里定义了:8000的WSS入口点,但Traefik容器的ports配置里没有映射这个端口到宿主机,外部无法访问。 - 路由与服务类型不匹配:WSS属于HTTP协议的升级,应该使用
http类型的路由和服务,而非tcp类型(除非处理纯TCP的WebSocket,但WSS是带TLS的WebSocket,基于HTTP协议)。 - ACME服务器版本过时:你使用的
acme-v01.api.letsencrypt.org已被废弃,需切换到v02版本。 - WSS路由未关联TLS与入口点:注释掉的TLS配置未启用,导致WSS连接无法通过加密通道建立。
修正后的完整配置
1. Traefik Docker-Compose配置
version: '3' services: reverse-proxy: image: traefik:v2.7.1 container_name: traefik ports: - "80:80" - "443:443" # 如果坚持用独立的8000端口做WSS,需添加以下映射,否则可省略,用443统一处理 # - "8000:8000" volumes: - /var/run/docker.sock:/var/run/docker.sock - $PWD/traefik.toml:/etc/traefik/traefik.toml - $PWD/acme.json:/acme.json restart: always networks: - web networks: web: external: true
2. Traefik.toml配置
[accessLog] [api] dashboard = true insecure = true [log] level = 'ERROR' [entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http] [entryPoints.web.http.redirections] [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" permanent = true [entryPoints.websecure] address = ":443" [entryPoints.websecure.http.tls] certResolver = "default" # 若不需要独立端口,可删除以下WSS入口点配置,用websecure统一处理 # [entryPoints.wss] # address = ":8000" # [entryPoints.wss.http.tls] # certResolver = "default" [providers] [providers.docker] watch = true exposedByDefault = false network = "web" [certificatesResolvers] [certificatesResolvers.default] [certificatesResolvers.default.acme] email = "contact@queel.io" storage = "acme.json" # 切换到v02版本的ACME服务器 caServer = "https://acme-v02.api.letsencrypt.org/directory" [certificatesResolvers.default.acme.tlsChallenge]
3. Node容器Docker-Compose配置
node: build: ./docker/node_api volumes: - ./node:/src tty: true networks: - web # 容器内部端口无需映射到宿主机,由Traefik负责转发 # ports: # - ":8000" # - ":8081" labels: - "traefik.docker.network=web" - "traefik.enable=true" # HTTPS API路由配置 - "traefik.http.routers.node.rule=Host(`api.${HOST}`)" - "traefik.http.routers.node.entrypoints=websecure" - "traefik.http.routers.node.tls=true" - "traefik.http.routers.node.tls.certResolver=default" - "traefik.http.services.node.loadbalancer.server.port=8000" # WSS路由配置(使用同一websecure入口点,通过Host区分) - "traefik.http.routers.wss.rule=Host(`ws.${HOST}`)" - "traefik.http.routers.wss.entrypoints=websecure" - "traefik.http.routers.wss.tls=true" - "traefik.http.routers.wss.tls.certResolver=default" # Traefik会自动处理WebSocket升级,无需额外中间件 - "traefik.http.services.wss.loadbalancer.server.port=8081" # 若坚持用独立的8000入口点,替换上方WSS的entrypoints为wss即可 # - "traefik.http.routers.wss.entrypoints=wss" - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https" depends_on: - elastic - neo working_dir: /src
关键配置说明
- 端口简化:无需给Node容器映射宿主机端口,Traefik通过Docker内部网络直接转发请求,更安全且避免端口冲突。
- WSS路由优化:直接复用
websecure(443端口)入口点,通过Host(ws.${HOST})区分WSS请求,Traefik会自动处理WebSocket协议升级。 - ACME服务器更新:切换到v02版本确保证书正常签发。
- TLS强制启用:给WSS路由明确开启
tls=true,保证连接加密(WSS本质就是WebSocket over TLS)。
内容的提问来源于stack exchange,提问作者user2626210
相关产品推荐
相关产品推荐

