使用 Traefik 进行 HTTP 路由
简介
在本地开发过程中,需要运行多个 HTTP 服务是很常见的。您可能同时拥有一个 API 和一个前端应用,一个用于模拟数据端点的 WireMock 服务,或者一个数据库可视化工具(如 phpMyAdmin 或 pgAdmin)。在许多开发设置中,这些服务暴露在不同的端口上,这不仅要求您记住哪个服务在哪个端口,还可能引入其他问题(例如 CORS)。
反向代理可以极大地简化这种设置,它作为唯一暴露的服务,然后根据请求 URL(通过路径或主机名)将请求路由到适当的服务。Traefik 是一个现代化的云原生反向代理和负载均衡器,它使开发和部署多服务应用程序变得更加容易。本指南将向您展示如何将 Traefik 与 Docker 结合使用,以增强您的开发环境。
在本指南中,您将学习如何
- 使用 Docker 启动 Traefik
- 配置路由规则以在两个容器之间分配流量
- 在容器化开发环境中使用 Traefik
- 使用 Traefik 将请求发送到非容器化工作负载
先决条件
要跟随本操作指南,需要满足以下先决条件
- Docker Desktop
- Node.js 和 yarn
- Docker 基础知识
在 Docker 中使用 Traefik
Traefik 的一个独特功能是它可以通过多种方式进行配置。当使用 Docker provider 时,Traefik 使用标签从其他正在运行的容器中获取其配置。Traefik 会监视引擎事件(用于容器启动和停止),提取标签,并更新其配置。
虽然有许多 Traefik 监控的标签,但最常见的两个是:
traefik.http.routers.<service-name>.rule- 用于指示路由规则(在此查看所有可用规则)traefik.http.services.<service-name>.loadbalancer.server.port- 指示 Traefik 应将请求转发到的端口。请注意,此容器端口无需在您的主机上暴露(在此阅读有关端口检测的信息)
让我们快速演示一下如何启动 Traefik,然后配置两个额外的容器,以便使用不同的主机名进行访问。
为了让两个容器能够相互通信,它们需要位于同一个网络上。使用
docker network create命令创建一个名为traefik-demo的网络。$ docker network create traefik-demo使用以下命令启动一个 Traefik 容器。该命令将 Traefik 暴露在 80 端口,挂载 Docker 套接字(用于监控容器以更新配置),并传递
--providers.docker参数以配置 Traefik 使用 Docker provider。$ docker run -d --network=traefik-demo -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik:v3.1.2 --providers.docker现在,启动一个简单的 Nginx 容器,并定义 Traefik 正在监视的标签以配置 HTTP 路由。请注意,Nginx 容器没有暴露任何端口。
$ docker run -d --network=traefik-demo --label 'traefik.http.routers.nginx.rule=Host(`nginx.localhost`)' nginx容器启动后,在浏览器中打开 http://nginx.localhost 以查看该应用(所有基于 Chromium 的浏览器都会在本地路由 *.localhost 请求,无需额外设置)。
启动第二个将使用不同主机名的应用程序。
$ docker run -d --network=traefik-demo --label 'traefik.http.routers.welcome.rule=Host(`welcome.localhost`)' docker/welcome-to-docker容器启动后,在浏览器中打开 http://welcome.localhost。您应该会看到一个“Welcome to Docker”网站。
在开发中使用 Traefik
现在您已经体验了 Traefik,是时候尝试在开发环境中使用它了。在这个例子中,您将使用一个具有前后端分离的示例应用程序。该应用栈具有以下配置:
- 所有到 /api 的请求都转到 API 服务
- 所有其他到 localhost 的请求都转到前端客户端
- 由于该应用使用 MySQL,db.localhost 应提供 phpMyAdmin,以便在开发过程中轻松访问数据库

该应用程序可以在 GitHub 上访问,地址为 dockersamples/easy-http-routing-with-traefik。
在
compose.yaml文件中,Traefik 使用以下配置:services: proxy: image: traefik:v3.1.2 command: --providers.docker ports: - 80:80 volumes: - /var/run/docker.sock:/var/run/docker.sock请注意,这与之前使用的配置基本相同,但现在是 Compose 语法。
客户端服务具有以下配置,它将启动容器并为其提供在 localhost 接收请求的标签。
services: # … client: image: nginx:alpine volumes: - "./client:/usr/share/nginx/html" labels: traefik.http.routers.client.rule: "Host(`localhost`)"api 服务具有类似的配置,但您会注意到路由规则有两个条件——主机必须是“localhost”,并且 URL 路径必须以“/api”为前缀。由于此规则更具体,Traefik 将会比客户端规则优先评估它。
services: # … api: build: ./dev/api volumes: - "./api:/var/www/html/api" labels: traefik.http.routers.api.rule: "Host(`localhost`) && PathPrefix(`/api`)"最后,
phpmyadmin服务被配置为接收对主机名“db.localhost”的请求。该服务还定义了环境变量以自动登录,这使得进入应用程序变得更容易一些。services: # … phpmyadmin: image: phpmyadmin:5.2.1 labels: traefik.http.routers.db.rule: "Host(`db.localhost`)" environment: PMA_USER: root PMA_PASSWORD: password在启动堆栈之前,如果 Nginx 容器仍在运行,请停止它。
就是这样。现在,您只需要用 docker compose up 启动 Compose 堆栈,所有的服务和应用程序就都准备好进行开发了。
将流量发送到非容器化工作负载
在某些情况下,您可能希望将请求转发到未在容器中运行的应用程序。在下面的架构图中,使用了与之前相同的应用程序,但 API 和 React 应用现在在本机上运行。

要实现这一点,Traefik 将需要使用另一种方法来配置自身。文件提供程序允许您在 YAML 文档中定义路由规则。这是一个示例文件:
http:
routers:
native-api:
rule: "Host(`localhost`) && PathPrefix(`/api`)"
service: native-api
native-client:
rule: "Host(`localhost`)"
service: native-client
services:
native-api:
loadBalancer:
servers:
- url: "http://host.docker.internal:3000/"
native-client:
loadBalancer:
servers:
- url: "http://host.docker.internal:5173/"此配置指示对 localhost/api 的请求将被转发到名为 native-api 的服务,该服务再将请求转发到 http://host.docker.internal:3000。主机名 host.docker.internal 是 Docker Desktop 提供的一个名称,用于向主机发送请求。
有了这个文件,唯一的变化就是 Traefik 的 Compose 配置。具体来说,有两件事发生了变化:
- 配置文件被挂载到 Traefik 容器中(具体的目标路径由您决定)
command已更新,以添加文件提供程序并指向配置文件的位置
services:
proxy:
image: traefik:v3.1.2
command: --providers.docker --providers.file.filename=/config/traefik-config.yaml --api.insecure
ports:
- 80:80
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./dev/traefik-config.yaml:/config/traefik-config.yaml启动示例应用
要运行将请求从 Traefik 转发到原生运行的应用的示例应用,请使用以下步骤:
如果您的 Compose 堆栈仍在运行,请使用以下命令停止它:
$ docker compose down使用提供的
compose-native.yaml文件启动应用程序。$ docker compose -f compose-native.yaml up打开 https:// 将返回 502 Bad Gateway,因为其他应用程序尚未运行。
通过运行以下步骤启动 API:
cd api yarn install yarn dev在一个新的终端中运行以下步骤来启动前端(从项目根目录开始):
cd client yarn install yarn dev在 https:// 打开应用。您应该会看到一个从 https:///api/messages 获取消息的应用。您也可以打开 http://db.localhost 直接从 Mongo 数据库查看或调整可用的消息。Traefik 将确保请求被正确路由到正确的容器或应用程序。
完成后,运行
docker compose down停止容器,并通过按ctrl+c停止 Yarn 应用。
回顾
运行多个服务不必需要复杂的端口配置和良好的记忆力。借助像 Traefik 这样的工具,可以轻松启动所需的服务并轻松访问它们——无论是应用本身(例如前端和后端)还是用于额外的开发工具(例如 phpMyAdmin)。