1. 为什么入口流量总在打架:从一次端口冲突说起
如果你手上只有一台 2C4G 的小主机,却跑了博客、API 网关、Grafana、MinIO 控制台四五个服务,那你大概率经历过这种场面:每个服务都想占 80 和 443,最后只能靠8081、8082、9000这种端口号硬撑。用户记不住,证书也没法统一挂,改一个服务的端口还得翻三份 compose 文件。
这就是 Edge Router 要解决的问题。Edge Router 直译是边缘路由器,你可以把它理解成「整个集群的传达室大爷」:所有从公网进来的请求先到它这里,它看一眼域名和路径,再决定把请求转给内部哪个容器。它不负责业务逻辑,只负责三件事——流量路由、TLS 终止、以及在第一道关口做限流和鉴权。
Traefik 就是这类软件里配置体验比较顺的一个。它和 Nginx 最大的区别在于:Nginx 的路由规则写死在配置文件里,加一个服务要 reload;Traefik 通过 provider 监听 Docker、Kubernetes 这类编排系统的变化,容器一起来,路由自动就注册好了。所以标题里说它是 Edge Router,重点不在「路由」这个词,而在于它天生就站在网络边缘,且配置是动态生长的。
这篇不聊概念史,直接给你一套能跑的骨架:静态配置定义入口,动态配置定义路由和中间件,然后用 curl 验证命中与 TLS 终止。适合正在给容器找统一入口的开发者。
2. 前置准备:TaoToken 与 Traefik 的定位分工
在动手前先把两件事分清楚,不然后面容易混。
Traefik 负责的是「请求从哪进、进到哪个容器」,它不产生模型能力。而如果你的入口后面挂的是大模型 API 服务,或者你想在本地用 Claude Code、Cline 这类编码工具接一个稳定的模型通道,那模型侧的 Key 和额度管理是另一件事。我自己的做法是:Traefik 管流量入口,模型调用走 TaoToken 的 API 通道,两边互不干扰。
TaoToken 的定位是模型调用入口,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。它和 Traefik 不冲突:Traefik 可以给内部服务做 TLS 终止和域名分发,TaoToken 则负责把模型请求转成统一的 OpenAI 兼容格式。如果你后面要验证路由是否真的把请求转到了后端,用一个模型对话请求当探针反而比curl /更直观,因为你能看到真实返回体。
需要提前准备的:
- 一台能跑 Docker 的机器,Docker 20.10+ 和 Docker Compose v2
- 一个域名,解析到这台机器(演示用
traefik.demo.local也行,本地 hosts 指过去) - 开放 80 和 443 端口
- 如果要自动签证书,域名得能公网访问;本地演示用自签证书即可
注意:下面所有配置里的域名、邮箱、路径都换成你自己的,别直接复制上线。
3. 可复制配置:静态骨架与动态骨架
Traefik 的配置分两层,这是理解它的关键。静态配置(static)决定 Traefik 进程怎么启动:监听哪些端口、去哪些 provider 拉路由、日志和证书存储放哪。动态配置(dynamic)决定请求进来后怎么走:routers 匹配规则、middlewares 做处理、services 指向真实后端。
3.1 静态配置 traefik.yml
# traefik.yml —— 静态配置,启动时读取一次 entryPoints: web: address: ":80" http: redirections: entryPoint: to: websecure scheme: https websecure: address: ":443" providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false watch: true file: directory: "/etc/traefik/dynamic" watch: true api: dashboard: true insecure: false log: level: INFO certificatesResolvers: le: acme: email: "you@example.com" storage: "/letsencrypt/acme.json" httpChallenge: entryPoint: web逐段说。entryPoints定义了两个入口:80 端口的web全部 301 跳到websecure,443 的websecure才是真正干活的。这一步就是 Edge Router 的「边缘」体现——TLS 终止发生在这一层,后端容器只需要说 HTTP。
providers里开了两个来源。docker让 Traefik 监听 Docker socket,容器带特定 label 就自动注册;exposedByDefault: false很重要,否则你机器上所有容器都会被暴露出去。fileprovider 指向/etc/traefik/dynamic,用来放手写的动态配置,适合非容器后端。
certificatesResolvers配了 Let's Encrypt 的 HTTP 挑战。本地演示如果没公网域名,把这段删掉,改用自签证书。
3.2 动态配置 routers 与 middlewares
在dynamic/routes.yml里写路由和中间件:
http: routers: api-router: rule: "Host(`traefik.demo.local`) && PathPrefix(`/api`)" entryPoints: - websecure service: api-service middlewares: - rate-limit - strip-api tls: certResolver: le dashboard-router: rule: "Host(`traefik.demo.local`) && PathPrefix(`/dashboard`)" entryPoints: - websecure service: api@internal middlewares: - auth-basic tls: certResolver: le middlewares: rate-limit: rateLimit: average: 100 burst: 50 strip-api: stripPrefix: prefixes: - "/api" auth-basic: basicAuth: users: - "admin:$apr1$xxxx$yyyy" services: api-service: loadBalancer: servers: - url: "http://host.docker.internal:9000"这里有几个点值得展开。rule是匹配表达式,Host加PathPrefix组合起来就是「域名 + 路径前缀」的路由条件,比 Nginx 的 location 更接近自然语言。middlewares是有序执行的:先限流,再剥掉/api前缀,最后才转给后端。stripPrefix这个中间件特别实用——后端服务不需要知道自己被挂在/api下面,它只管处理根路径。
api@internal是 Traefik 自带的 dashboard 服务,加上auth-basic中间件后就不会裸奔。生成 basicAuth 密码用htpasswd -nb admin yourpassword,把输出填进 users 数组。
3.3 docker-compose 把两层拼起来
services: traefik: image: traefik:v3.0 ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik.yml:/etc/traefik/traefik.yml:ro - ./dynamic:/etc/traefik/dynamic:ro - ./letsencrypt:/letsencrypt restart: unless-stopped whoami: image: traefik/whoami labels: - "traefik.enable=true" - "traefik.http.routers.whoami.rule=Host(`traefik.demo.local`) && PathPrefix(`/who`)" - "traefik.http.routers.whoami.entrypoints=websecure" - "traefik.http.routers.whoami.tls.certresolver=le" - "traefik.http.services.whoami.loadbalancer.server.port=80"whoami这个容器是官方提供的回显服务,用来验证路由最合适——它会把收到的请求头原样返回。注意 label 的命名规律:traefik.http.routers.<名字>.rule,名字自己起,同一个名字下的配置会自动归到一条路由上。
4. 验证请求:curl 看路由命中与 TLS 终止
配置写完,docker compose up -d起来。先看 Traefik 日志有没有报错:
docker compose logs -f traefik正常的话你会看到Configuration loaded from file和Starting provider *docker之类的行。然后开始验证。
第一步,验证 HTTP 到 HTTPS 的跳转:
curl -I http://traefik.demo.local/who期望看到301 Moved Permanently,Location: https://traefik.demo.local/who。这说明webentryPoint 的重定向生效了,边缘的第一层规则没问题。
第二步,验证路由命中。用-k跳过自签证书校验(有正式证书就不需要):
curl -k https://traefik.demo.local/who返回体里应该能看到Hostname: <容器ID>、X-Forwarded-Proto: https这些字段。X-Forwarded-Proto是 https 就说明 TLS 终止确实发生在 Traefik 这一层,后端收到的是解密后的 HTTP 请求。这一步是 Edge Router 的核心证据。
第三步,验证中间件。请求/api路径:
curl -k -i https://traefik.demo.local/api/health如果后端返回的路径里没有/api前缀,说明stripPrefix生效了。再快速打 200 次看限流:
for i in $(seq 1 200); do curl -k -s -o /dev/null -w "%{http_code}\n" https://traefik.demo.local/api/health; done | sort | uniq -c正常会看到大部分 200,少量 429。429 就是rateLimit中间件在边缘拦下来的,后端根本没被打到。
第四步,如果你后面要接模型服务,可以用一个对话请求当探针。TaoToken 的模型对话入口在 https://taotoken.net/api ,把后端 service 指向你的模型网关,然后用:
curl -k https://traefik.demo.local/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TAOTOKEN_KEY" \ -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}'能拿到正常 JSON 返回,就说明从边缘到模型通道整条链路是通的。
5. 本篇常见错排查
路由不生效,404 或 502。先看 dashboard,https://traefik.demo.local/dashboard里 Routers 页面会列出所有已注册路由。如果路由压根没出现,多半是 label 写错或者容器没加traefik.enable=true。如果路由出现了但状态是 warning,看它提示的 service 找不到——通常是loadbalancer.server.port没写或写错。
TLS 证书签不下来。HTTP 挑战要求 80 端口能从公网访问到 Traefik。如果你前面还套了一层 Nginx 或云负载均衡,挑战请求到不了 Traefik,就会一直卡在 pending。本地演示直接删掉 certResolver,用自签证书。
exposedByDefault忘了关。默认是 true,意味着你机器上所有容器都会被 Traefik 接管并尝试路由。生产环境一定设成 false,只让带 label 的容器暴露。
Docker socket 权限问题。挂载/var/run/docker.sock时如果容器内用户没权限,provider 会报permission denied。加:ro只读挂载,或者把容器用户加到 docker 组。
中间件顺序反了。stripPrefix如果放在rateLimit前面,限流的路径统计会基于剥前缀后的路径,可能和预期不符。中间件按数组顺序执行,想清楚再排。
改了动态配置不生效。file provider 开了watch: true会自动重载,但如果你把文件挂载成了单个文件而不是目录,inotify 可能监听不到。挂目录更稳。
6. 把入口收拢之后,下一步接什么
Traefik 这套骨架跑通后,你其实已经拿到了一个最小可用的边缘层:80/443 统一入口、自动跳转、按域名和路径分发、TLS 终止、限流和鉴权都在边缘完成。后端容器只管说 HTTP,不用再操心证书和端口。
接下来看你的场景分流。如果你是在排障接入层的问题,比如路由规则写不对、证书签不下来,重点看 API Keys 和接入文档,把模型通道的鉴权先理顺:https://taotoken.net/api-keys 和 https://taotoken.net/doc 。如果你只是想先验证某个模型能不能通,直接用模型对话页面发一条请求最快:https://taotoken.net/chat 。而如果你是要长期跑编码工具或者 Agent,需要稳定的额度和调用计划,那 Coding Plan 更合适:https://taotoken.net/coding-plan 。
边缘路由的价值不在于它多复杂,而在于它把「请求怎么进来」这件事从每个业务服务里抽出来,收拢到一层。Traefik 的配置文件就是这层收拢的骨架,骨架搭对了,后面加服务只是加几行 label 的事。