Traefik 结合 Docker 快速入门:用 Docker Compose 部署网关、暴露 Dashboard 并验证容器路由
本文基于 Traefik 官方 Quick Start 指南(docs/content/getting-started/docker.md),讲解如何用 Docker / Docker Compose 安装 Traefik v3.7、开启仪表盘、通过容器 Label 暴露一个示例服务并验证路由生效。读完本篇,你不仅能复现一套最小可用的 Traefik + Docker 环境,还能从源码层面理解 --providers.docker=true 背后 Docker provider 是如何监听容器事件、解析 Label 并生成动态路由配置的。
前置条件
开始之前,宿主机需要安装:
- Docker
- Docker Compose(可选,若你打算直接用
docker run部署可省略)
整个流程只依赖这两样。Traefik 自身以官方镜像 traefik:v3.7 运行,Docker 是 Traefik 的“一等公民” provider,它对 Docker 容器和服务提供原生支持。
安装 Traefik
方式一:使用 Docker Compose
创建一个 Docker Compose 文件,如下所示:
# docker-compose.yml
services:
traefik:
image: traefik:v3.7
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
这份配置做了四件事:
| 配置项 | 作用 |
|---|---|
端口 80 / 8080 |
80 用于普通 Web 流量(由 --entrypoints.web.address=:80 定义);8080 用于仪表盘访问,因为启用了 --api.insecure=true(仅限开发环境) |
--api.insecure=true |
让 API 与 Dashboard 直接在名为 traefik 的默认入口点上无认证暴露。从源码 pkg/config/static/static_config.go 可以看到,API.Insecure 的官方描述即为“Activate API directly on the entryPoint named traefik”,且 Dashboard 默认为 true,默认入口点地址为 :8080 |
--providers.docker=true |
启用 Docker provider,使 Traefik 能自动发现本机 Docker 容器 |
挂载 /var/run/docker.sock |
让 Traefik 容器可以访问 Docker API,从而完成容器发现。注意 Docker 默认 Unix socket 正是 provider 的默认 endpoint:pkg/provider/docker/pdocker.go 中 SetDefaults() 将 Endpoint 设为 unix:///var/run/docker.sock |
启动 Traefik:
docker-compose up -d
方式二:使用 Docker CLI
也可以直接用 Docker CLI 运行。先创建配置文件:
# traefik.yml
api:
insecure: true
entryPoints:
web:
address: ":80"
providers:
docker: {}
然后启动:
docker run -d \
-p 80:80 \
-p 8080:8080 \
-v $PWD/traefik.yml:/etc/traefik/traefik.yml \
-v /var/run/docker.sock:/var/run/docker.sock \
traefik:v3.7
该命令与 Compose 示例的配置语义完全一致:暴露 80/8080 两个端口、挂载静态配置文件与 Docker socket。区别仅在于静态配置由命令行参数改为挂载的 traefik.yml。
暴露 Dashboard
由于显式启用了 insecure 模式,仪表盘 可以在 无需任何认证 的情况下通过 8080 端口访问。请勿在生产环境启用该标志(--api.insecure=true)。
在浏览器中访问:
http://localhost:8080/dashboard/
生产环境中应使用
--api=true配合独立的traefik入口点,并结合 Basic Auth、OIDC 或 JWT 等手段保护 API,相关文档见 API Dashboard 参考。
部署一个示例应用
创建一个 whoami 服务(Traefik 官方的请求回显容器),并通过 Label 声明路由规则:
# whoami.yml
services:
whoami:
image: traefik/whoami
labels:
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
这里的 Label 遵循 traefik.http.routers.<name>.rule 的命名约定:当请求 Host 头为 whoami.localhost 时,命中名为 whoami 的 HTTP Router。
应用配置:
docker-compose -f whoami.yml up -d
容器启动后,Docker provider 会立即感知到该容器并将其路由配置推送给 Traefik——这一步无需重启 Traefik,是 provider 的实时事件监听机制带来的能力(原理见下文“源码视角”一节)。
验证部署
使用 curl 验证应用是否被正确暴露:
curl http://whoami.localhost
Hostname: 068c0a29a8b7
IP: 127.0.0.1
IP: ::1
IP: 192.168.147.3
RemoteAddr: 192.168.147.2:56006
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/8.7.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.147.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: 9232cdd4fd6c
X-Real-Ip: 192.168.147.1
返回体中的 X-Forwarded-* / X-Real-Ip 头由 Traefik 反向代理层注入,说明请求确实经过了 Traefik 转发。你也可以在浏览器中打开 http://whoami.localhost 得到同样的回显:
接着打开 Traefik 仪表盘的 HTTP Routers 区域,可以看到 whoami.localhost 这条路由由 Docker provider 管理:
至此,你已成功部署 Traefik 并在 Docker 中完成了第一条路由配置。
源码视角:Docker provider 如何把容器变成路由
上述“启动 whoami 后路由立即出现”并非魔法,可以从源码中理清其完整链路(位于 pkg/provider/docker/ 目录):
-
建立连接与初始发现。
Provider.Provide()(pkg/provider/docker/pdocker.go)在独立协程中创建 Docker API client,调用ServerVersion确认连通,然后listContainers拉取全部容器,交给DynConfBuilder.build()生成一份dynamic.Configuration,通过configurationChan通道推给主进程。 -
事件监听实现热更新。默认
Watch = true(SetDefaults()中设定,pkg/provider/docker/pdocker.go)。当启用 watch 时,provider 通过dockerClient.Events()订阅容器事件,只关心三类 action:start、die以及以health_status开头的事件(pkg/provider/docker/pdocker.go)。每收到一次事件就重新列出容器、重建配置并再次写入通道——这就是 whoami 容器一启动、路由就出现在仪表盘上的原因。若整个流程出错,provider 会使用指数退避(backoff.RetryNotify)持续重试,而不是直接崩溃。 -
Label 解码与配置构建。
build()(pkg/provider/docker/config.go)对每个容器依次:- 调用
keepContainer()判断容器是否应被纳入(受exposedByDefault/traefik.enable控制,默认ExposedByDefault = true,即不写 Label 的容器也会被暴露); - 用
label.DecodeConfiguration()把traefik.http.*、traefik.tcp.*、traefik.udp.*等 Label 解码为结构化配置; - 先处理 TCP/UDP 服务与路由,再构建 HTTP 服务配置;
- 最后调用
provider.BuildRouterConfiguration(),将容器名作为 service 名、配合defaultRuleTpl模板完成 Router 与 Rule 的绑定。
- 调用
-
defaultRule 兜底。如果容器没有通过 Label 定义 rule,provider 会套用默认规则。该模板在 pkg/provider/docker/shared.go 中定义为:
const DefaultTemplateRule = "Host(`{{ normalize .Name }}`)"即默认按“归一化后的容器名作为 Host”生成规则。你还可以通过
--providers.docker.defaultRule用 Go template(支持 sprig 函数,可访问.Name、.ContainerName、.Labels)自定义兜底规则,例如Host(\{{ .Name }}.example.com`)`。 -
端口探测。Traefik 从 Docker API 获取容器的私有 IP 与端口:容器只暴露一个端口时直接使用该端口;暴露多个端口时取最小端口(如同时暴露 80 与 8080 则用 80);未暴露端口时需通过
traefik.http.services.<name>.loadbalancer.server.portLabel 手动指定。以上规则与endpoint(支持unix://、tcp://、ssh://、http://等 Docker API 接入方式)、useBindPortIP、constraints、exposedByDefault等全部配置项说明,可参考官方 provider 文档 docs/content/reference/install-configuration/providers/docker.md。
安全提示:挂载 docker.sock 的风险
快速入门中挂载 /var/run/docker.sock 是为了让 Traefik 能“看到”容器,但官方文档明确指出:不受限制地访问 Docker API 是安全隐患——一旦 Traefik 被攻破,攻击者可能借此控制宿主机(Docker daemon 等价于 root 权限入口)。生产环境可考虑以下缓解手段(详见 Docker provider 文档的 Docker API Access 章节):
- 通过 TCP/SSH 暴露 Docker socket 而非 Unix socket,配合客户端证书认证(provider 的
tls.ca/tls.cert/tls.key选项即为此设计); - 用 socket proxy 类工具对 socket 的调用做鉴权与白名单过滤;
- 借助
--providers.docker.constraints或exposedByDefault=false+traefik.enable=true收窄 provider 的暴露范围; - 将 socket 只暴露给 Traefik 所在的私有网络。
下一步
部署完成后,建议按以下顺序继续深入(对应官方文档路径):
- 配置 TLS:docs/content/reference/routing-configuration/http/tls/overview.md
- 使用中间件:docs/content/reference/routing-configuration/http/middlewares/overview.md
- 启用指标采集:docs/content/reference/install-configuration/observability/metrics.md
- 深入 Docker provider:docs/content/reference/install-configuration/providers/docker.md
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


