You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Traefik基于协议将app.example.com路由到不同Docker容器?

用Traefik实现同一域名下REST与WebSocket服务的路由分流

这是Traefik里非常典型的基于请求特征的路由场景,咱们直接用Docker Compose来配置,步骤清晰又好维护。

核心思路

Traefik可以通过请求头特征区分WebSocket请求(因为WebSocket是从HTTP协议升级而来的,请求里会带Upgrade: websocketConnection: Upgrade这两个关键头),再结合域名匹配,把普通HTTP请求转发到REST容器,把WebSocket升级请求转发到WebSocket容器。

完整Docker Compose配置

先上完整的docker-compose.yml,我会逐行解释关键部分:

version: '3.8'

# 自定义网络,让Traefik和两个应用容器互通
networks:
  traefik-net:
    external: false

services:
  # Traefik 反向代理服务
  traefik:
    image: traefik:v2.10  # 用稳定版,避免兼容性问题
    command:
      - "--api.insecure=true"  # 开启API面板(仅测试用,生产建议关闭或加认证)
      - "--providers.docker=true"  # 启用Docker自动发现
      - "--providers.docker.exposedbydefault=false"  # 只处理显式配置了Traefik标签的容器
      - "--entrypoints.web.address=:80"  # 监听80端口作为HTTP入口
    ports:
      - "80:80"
      - "8080:8080"  # API面板端口,测试用
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"  # 挂载Docker套接字,让Traefik能发现容器
    networks:
      - traefik-net

  # REST 服务容器
  rest-service:
    image: your-rest-image:latest  # 替换成你的REST应用镜像
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"  # 允许Traefik处理这个容器
      - "traefik.http.routers.rest.rule=Host(`app.example.com`)"  # 匹配域名app.example.com的请求
      - "traefik.http.routers.rest.entrypoints=web"  # 使用web入口点
      - "traefik.http.services.rest.loadbalancer.server.port=80"  # 转发到容器的80端口

  # WebSocket 服务容器
  ws-service:
    image: your-ws-image:latest  # 替换成你的WebSocket应用镜像
    networks:
      - traefik-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.ws.rule=Host(`app.example.com`) && Headers(`Upgrade`, `websocket`) && Headers(`Connection`, `Upgrade`)"  # 匹配域名+WebSocket升级头
      - "traefik.http.routers.ws.entrypoints=web"
      - "traefik.http.services.ws.loadbalancer.server.port=90"  # 转发到容器的90端口

关键配置解释

  1. 自定义网络traefik-net确保三个容器在同一个网络内,Traefik可以直接通过容器名访问应用服务,不需要暴露端口到宿主机。
  2. Traefik核心配置
    • --providers.docker=true:开启Docker自动发现,Traefik会自动读取容器上的Traefik标签来配置路由。
    • --providers.docker.exposedbydefault=false:避免Traefik自动代理所有容器,只处理显式开启traefik.enable=true的容器。
  3. REST服务路由
    • 仅通过Host(app.example.com)匹配所有发往该域名的HTTP请求,转发到容器的80端口。
  4. WebSocket服务路由
    • 除了匹配域名,还通过Headers规则筛选出带有WebSocket升级头的请求,转发到容器的90端口。Traefik会自动处理WebSocket的连接保持,不需要额外配置。

验证方法

  • 测试REST服务:用curl发送普通HTTP请求
    curl http://app.example.com/your-rest-endpoint
    
    应该能得到REST服务的响应。
  • 测试WebSocket服务:用wscat(需要先安装npm install -g wscat)连接
    wscat -c ws://app.example.com/your-ws-endpoint
    
    如果连接成功,就说明路由生效了。

生产环境注意事项

  • 关闭Traefik的api.insecure=true,改用认证(比如Basic Auth)或者直接关闭API面板。
  • 建议配置HTTPS(Let's Encrypt自动证书),把WebSocket换成wss://,对应Traefik的HTTPS入口点。
  • 如果你的WebSocket服务有特定路径,可以在路由规则里加上Path(/ws)之类的条件,进一步精准匹配。

内容的提问来源于stack exchange,提问作者dov.amir

火山引擎 最新活动