使用 Traefik 进行 HTTP 路由
引言
在本地开发期间,通常需要运行多个 HTTP 服务。您可能同时拥有 API 和前端应用程序、用于模拟数据端点的 WireMock 服务,或者数据库可视化工具(例如 phpMyAdmin 或 pgAdmin)。在许多开发环境中,这些服务暴露在不同的端口上,这需要您记住每个端口上是什么,但也会引入其他问题(例如 CORS)。
通过充当唯一的暴露服务,然后根据请求 URL(通过路径或主机名)将请求路由到适当的服务,反向代理可以极大地简化此设置。Traefik 是一个现代的云原生反向代理和负载均衡器,它可以使开发和部署多服务应用程序变得更加容易。本指南将向您展示如何将 Traefik 与 Docker 配合使用来增强您的开发环境。
在本指南中,您将学习如何
- 使用 Docker 启动 Traefik
- 配置路由规则以在两个容器之间分流流量
- 在容器化开发环境中使用 Traefik
- 使用 Traefik 将请求发送到非容器化工作负载
先决条件
按照本操作指南进行操作需要满足以下先决条件
- Docker Desktop
- Node.js 和 yarn
- Docker 基础知识
将 Traefik 与 Docker 配合使用
Traefik 的独特功能之一是它可以通过多种方式进行配置。当使用 Docker 提供程序时,Traefik 使用 labels 从其他正在运行的容器获取其配置。Traefik 会监听引擎事件(用于容器启动和停止),提取 labels,并更新其配置。
虽然有 许多 Traefik 监控的 labels,但最常用的两个是
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 socket(用于监控容器以更新配置),并传递
--providers.docker
参数来配置 Traefik 使用 Docker 提供程序。$ 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 路由的 labels。请注意,此 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。您应该会看到一个“欢迎使用 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 语法。
客户端服务具有以下配置,它将启动容器并为其提供 labels,以便在 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 需要使用另一种方法来配置自己。File provider 允许您在 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
命令更新为添加 file provider 并指向配置文件的位置
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
打开 http://localhost 将返回 502 Bad Gateway 错误,因为其他应用程序尚未运行。
通过运行以下步骤启动 API:
cd api yarn install yarn dev
在新的终端窗口中运行以下步骤启动前端(从项目根目录开始)
cd client yarn install yarn dev
在 http://localhost 打开应用程序。您应该会看到一个从 http://localhost/api/messages 获取消息的应用程序。您也可以打开 http://db.localhost 直接从 Mongo 数据库查看或调整可用消息。Traefik 将确保请求被正确路由到相应的容器或应用程序。
完成后,运行
docker compose down
停止容器,并通过按ctrl+c
停止 Yarn 应用程序。
总结
运行多个服务不再需要复杂的端口配置和良好的记忆力。借助 Traefik 等工具,您可以轻松启动所需的服务并轻松访问它们——无论是应用程序本身(如前端和后端)还是额外的开发工具(如 phpMyAdmin)。