Dokku 集成 Traefik 代理:基于 Docker Label 的应用路由、健康检查与 Letsencrypt 配置实战指南
2026/9/11 5:58:14 网站建设 项目流程

Dokku 集成 Traefik 代理:基于 Docker Label 的应用路由、健康检查与 Letsencrypt 配置实战指南

【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku

导读

本文面向使用 Dokku(Docker 驱动的 PaaS)构建与托管应用生命周期的开发者,系统讲解如何将默认的 nginx 代理切换为 Traefik,并利用 Traefik 的 Docker Label 集成实现应用路由。你将掌握:Traefik 插件的路由规则与端口映射约定、app.json健康检查到 Traefik 标签的自动转换、容器生命周期管理(traefik:start/stop/logs/show-config)、自定义标签注入、Letsencrypt 证书签发(TLS-ALPN-01 与 DNS-01 两种挑战模式),以及通过traefik:report排障与审计配置的完整方法。文中所有结论均可在 plugins/traefik-vhosts 插件的源码与模板中找到实现依据。

Traefik 插件概述与工作原理

Traefik 是 Dokku 的可选反向代理实现,自 Dokku 0.28.0 起提供官方集成(见 docs/networking/proxies/traefik.md 顶部说明)。与 nginx 代理“由 Dokku 生成并管理配置文件”不同,Traefik 插件走的是Docker Label 驱动的路线:Dokku 在部署时把路由规则以容器标签的形式注入web进程容器,Traefik 通过 Docker Provider 监听这些标签并自动完成服务发现与路由,无需 Dokku 侧再维护代理配置文件。

插件的命令入口如下(完整命令清单见 plugins/traefik-vhosts/commands 与 plugins/traefik-vhosts/help-functions):

traefik:report [<app>] [<flag>] # Displays a traefik report for one or more apps traefik:logs [--num num] [--tail] # Display traefik log output traefik:set <app> <property> (<value>) # Set or clear an traefik property for an app traefik:show-config <app> # Display traefik compose config traefik:start # Starts the traefik server traefik:stop # Stops the traefik server

前置要求

使用 Traefik 插件的前提是 Docker 主机已安装docker-compose-plugin。插件通过docker compose up/docker compose down管理 Traefik 容器——这一点可以直接在 plugins/traefik-vhosts/command-functions 的cmd-traefik-start/cmd-traefik-stop中看到:两者都会先调用fn-is-compose-installed检查 compose 插件,失败则直接dokku_log_fail "Required docker compose plugin is not installed",随后分别调用 common 模块的compose-upcompose-down

# 安装 docker-compose-plugin(以 Debian/Ubuntu 系为例,具体以 Docker 官方安装文档为准) apt-get install docker-compose-plugin

路由规则:理解 Traefik 插件的边界

[!WARNING] 在同一台 Dokku 主机上同时使用多个代理插件会导致请求路由异常,应当避免。由于默认代理实现是 nginx,切换 Traefik 前建议先停止 nginx 服务。

Traefik 插件的路由行为遵循以下规则(同样反映在 plugins/traefik-vhosts/docker-args-process-deploy 的标签注入逻辑中):

  • Traefik 集成通过容器上附加的Docker labels暴露,标签变更需要应用重新部署或重建(dokku ps:rebuild)才会生效;
  • 虽然 Traefik 会尊重其他容器携带的标签,但插件只给web进程注入 Traefik 标签docker-args-process-deployPROC_TYPE != "web"时直接return);
  • 仅支持http:80https:443端口映射,多端口映射时只代理一个 http 端口和一个 https 端口;
  • 找不到http:80映射时,取第一个 http 端口映射为 http 请求服务;
  • 找不到https:443映射时,取第一个 https 端口映射为 https 请求服务;
  • 完全没有 https 映射时,https 请求会复用http:80的容器端口;
  • 容器通过运行与健康检查后,请求立即被路由;
  • app.json中带path属性的 readiness 健康检查会被自动转换为 Traefik 健康检查标签。

从源码看,端口映射的解析发生在 docker-args-process-deploy:插件遍历ports-get返回的端口映射列表,分别记录httphttps方案下的“首个候选端口”和“恰好为 80/443 的精确端口”,优先使用精确映射,找不到时回退到首个候选并在日志中打印Warning: http:80 port mapping not found

标签注入的完整链路

部署时,docker-args-process-deploy触发器会拼装出如下形式的标签($APP-$PROC_TYPE形如node-js-app-web):

--label traefik.enable=true --label traefik.http.services.$APP-$PROC_TYPE-http.loadbalancer.server.port=<container-port> --label traefik.http.routers.$APP-$PROC_TYPE-http.entrypoints=<http-entry-point> --label traefik.http.routers.$APP-$PROC_TYPE-http.service=$APP-$PROC_TYPE-http --label "traefik.http.routers.$APP-$PROC_TYPE-http.rule=Host(`app.example.com`) || Host(`app2.example.com`)"

域名为多个时,规则由Host(\domain1`) || Host(`domain2`)拼接而成(见 [docker-args-process-deploy](https://link.gitcode.com/i/add60937da2ec4faa8b8e1b5b7398633#L84-L99));存在 https 端口时还会追加traefik.http.routers...https.tls.certresolver=leresolver`,将 TLS 证书解析器指向插件内置的 letsencrypt resolver。

健康检查:从 app.json 到 Traefik 标签

当应用的app.json中定义了带path属性的 readiness 健康检查时,Dokku 自动生成 Traefik 健康检查标签,Traefik 会在路由流量前先对容器执行健康检查。属性映射关系如下:

app.json PropertyTraefik Label PropertyDescription
pathhealthcheck.pathThe HTTP path to check (required)
schemehealthcheck.schemeThe scheme to use (httporhttps)
porthealthcheck.portThe port to check
timeouthealthcheck.timeoutTimeout in seconds (formatted asXs)
waithealthcheck.intervalInterval between checks in seconds (formatted asXs)

示例app.json

{ "healthchecks": { "web": [ { "name": "web readiness check", "path": "/health", "timeout": 5, "type": "readiness", "wait": 10 } ] } }

[!NOTE] 只使用第一个带path属性的 readiness 健康检查。liveness、startup 及基于命令的健康检查不会被转换为 Traefik 标签。

实现层面,docker-args-process-deploy 使用 jq 过滤器选择健康检查并生成对应标签:

hc_filter='.healthchecks.web // [] | map(select(.type == "readiness" and .path != null and .path != "")) | .[0]'

随后将timeoutwait分别格式化为${timeout}s${wait}s,写入loadbalancer.healthcheck.timeoutloadbalancer.healthcheck.interval标签——与文档映射表中“formatted asXs”的说明完全一致。

切换到 Traefik 代理

为指定应用启用 Traefik 代理使用proxy:set

dokku proxy:set node-js-app type traefik

这将启用基于 Docker 标签的 Traefik 集成,此后所有部署都会注入 Traefik 可读取的路由标签。由于标签集成机制,需要一次部署或重建后请求才会被成功路由

dokku ps:rebuild node-js-app

域名或端口映射的任何变更同样需要一次部署或重建。插件通过docker-args-process-deploy中的proxy-typeproxy-is-enableddomains-vhost-enabled三个触发器组合判断是否注入标签(docker-args-process-deploy),并在core-post-deploy阶段打印Routing app via traefik(见 plugins/traefik-vhosts/core-post-deploy)。

管理 Traefik 容器

启动 Traefik 容器

dokku traefik:start

该命令内部通过docker compose up启动 Traefik 容器。从 command-functions 可以看到它还会先写入proxy-status属性为started,并创建权限为600${DOKKU_LIB_ROOT}/data/traefik/traefik-acme.json(ACME 证书存储文件),然后基于 sigil 模板生成 compose 文件并执行compose-up

停止 Traefik 容器

dokku traefik:stop

容器会被停止并移除。若容器本就没有运行,该命令不会产生任何副作用。实现上调用compose-down并将proxy-status写为stopped(command-functions)。

查看 Traefik 容器日志

dokku traefik:logs

支持两个修饰参数:

--num NUM # the number of lines to display --tail # continually stream logs

组合使用示例——持续输出日志并保留最近 10 行历史:

dokku traefik:logs --tail --num 10

实现中--num默认值为 100,--tail对应 docker logs 的--follow(internal-functions),日志容器名为traefik-traefik-1

显示 Traefik compose 配置

调试时可用traefik:show-config输出当前生成的 compose 配置:

dokku traefik:show-config

该命令将 sigil 模板渲染结果打印到标准输出。模板位于 plugins/traefik-vhosts/templates/compose.yml.sigil,其中包含入口点声明(--entrypoints.http.address=:80)、Docker provider(--providers.docker--providers.docker.exposedByDefault=false)、API/Dashboard 开关、ACME resolver、数据卷(/var/run/docker.sock只读挂载与${DOKKU_LIB_ROOT}/data/traefik)等关键配置。插件还支持通过traefik-template-source触发器替换自定义模板(internal-functions)。

自定义 Traefik 容器镜像

默认镜像被硬编码,但可通过--global标志覆盖image属性:

dokku traefik:set --global image traefik:v2.8

注意:当前仓库 plugins/traefik-vhosts/Dockerfile 的FROM traefik:v3.7.12才是实际默认镜像。未设置image属性时,computed 值会从该 Dockerfile 的FROM行解析得到(internal-functions)。因此上述示例命令请按你的目标版本改写,例如dokku traefik:set --global image traefik:v3.7.12。文档中报告示例输出的traefik:v2.8属于历史示例,不代表当前仓库的默认值。

全局属性配置

所有 Traefik 属性均为 global-only 作用域,即只能通过--global标志设置(traefik:set命令会对非全局 key 报错,见 subcommands/set)。

修改 entrypoint 名称

自托管 Traefik 实例的入口点名称可能与默认的httphttps不同,可通过http-entry-pointhttps-entry-point属性自定义:

dokku traefik:set --global http-entry-point web dokku traefik:set --global https-entry-point websecure

设置后需重建或重新部署应用,标签中的entrypoints值才会更新。

修改日志级别

Traefik 日志级别默认ERROR,可通过log-level属性调整(computed 值会强制大写):

dokku traefik:set --global log-level DEBUG

修改后需要重启 Traefik 容器:

dokku traefik:restart # 实际操作为 traefik:stop && traefik:start

[!NOTE] 插件本身没有traefik:restart子命令,文档明确要求“修改后重启容器”,可依次执行dokku traefik:stopdokku traefik:start。compose 模板中设置了restart: unless-stopped(compose.yml.sigil)。

Label 管理:注入自定义 Traefik 标签

插件允许为应用添加自定义容器标签,用于扩展默认行为之外的 Traefik 配置(例如中间件、限流、重定向等,可参考 Traefik 官方文档中可用的标签)。这些标签在部署时注入容器。

添加标签

dokku traefik:labels:add node-js-app traefik.directive value

这会为应用容器添加traefik.directive=value标签,之后需重建或重新部署:

dokku ps:rebuild node-js-app

移除标签

dokku traefik:labels:remove node-js-app traefik.directive

移除后同样需要重建或重新部署才生效。

查看标签

查看应用全部自定义标签:

dokku traefik:labels:show node-js-app

查看指定标签的值:

dokku traefik:labels:show node-js-app traefik.directive

实现上,这三个命令分别委托给 proxy 插件的cmd-proxy-labels-add/remove/show,并传入代理类型traefik(command-functions);部署时自定义标签从fn-proxy-get-labels-file-path "traefik" "$APP"指向的标签文件读取并追加到docker run参数(docker-args-process-deploy)。

SSL 配置:Letsencrypt 证书自动化

Traefik 插件仅支持通过其内置 letsencrypt 集成签发自动证书certs插件托管的证书会被忽略。

启用 letsencrypt 集成

默认情况下 letsencrypt 是禁用的,https 端口映射会被忽略。设置letsencrypt-email属性即可启用:

dokku traefik:set --global letsencrypt-email automated@dokku.sh

启用后需要重建应用并重启 Traefik 容器,此后所有 http 请求都会被重定向到 https。从 compose.yml.sigil 可以看到,设置邮箱后模板会追加 http 到 https 的重定向入口点配置并开放443端口;ACME resolver(leresolver)的caserveremailstorage=/data/acme.json也会被一并渲染(compose.yml.sigil)。

自定义 letsencrypt 服务器

默认使用 letsencrypt 生产服务器,可通过letsencrypt-server属性切换到其他 ACME 目录(例如预发布环境):

dokku traefik:set --global letsencrypt-server https://acme-staging-v02.api.letsencrypt.org/directory

修改后需重启 Traefik 容器并重建应用以从新服务器获取证书。

切换到 DNS-01 挑战模式

默认 Traefik 使用 TLS-ALPN-01 挑战(challenge-mode默认tls)。当需要通配符证书、或 443 端口不可达时,可切换到 DNS-01 挑战:

  1. 设置挑战模式为dns
dokku traefik:set --global challenge-mode dns
  1. 设置 DNS 提供商:
dokku traefik:set --global dns-provider cloudflare
  1. 配置 DNS 提供商所需的环境变量,变量名前缀为dns-provider-
dokku traefik:set --global dns-provider-cf_api_email user@example.com dokku traefik:set --global dns-provider-cf_api_key your-api-key

dns-provider-前缀会被剥离、变量名大写后传入 Traefik 容器。例如dns-provider-cf_api_email变为CF_API_EMAIL。这一转换在 compose.yml.sigil 中通过replace "dns-provider-" "" | upper完成,所有dns-provider-*属性由fn-traefik-dns-provider-env-vars收集(internal-functions)。

每个配置的变量会以--traefik-global-dns-provider-<env_var>形式出现在traefik:report中。由于这些值是提供商凭据,默认报告输出(包括聚合的dokku report)会将其掩码为*******;显式请求该 flag 或使用 json 格式渲染时返回原始值:

dokku traefik:report --global --traefik-global-dns-provider-cf_api_email
dokku traefik:report --global --format json | jq -r '."global-dns-provider-cf_api_email"'

配置完成后需重启 Traefik 容器并重建应用。支持哪些 DNS 提供商及其必需环境变量,以 Traefik 官方 DNS Challenge 文档为准。切换回 TLS 挑战模式:

dokku traefik:set --global challenge-mode tls

掩码逻辑在 report.go 的maskedReportFunc中实现:除--format json或显式指定对应 flag 外,非空值一律替换为*******dns-provider-*动态属性同样经过该函数处理(report.go)。

暴露 Traefik API 与 Dashboard

Traefik 暴露了 API 和 Dashboard,Dokku 出于安全原因默认全部关闭,可按需开启并定制。

[!WARNING] 启用 Dashboard 的用户应同时启用 API 基础认证。

启用 API

dokku traefik:set --global api-enabled true

启用后需重启 Traefik 容器。

启用 Dashboard

dokku traefik:set --global dashboard-enabled true

启用后需重启 Traefik 容器。从 compose.yml.sigil 可看到,API 开启后会为 Traefik 容器自身注入traefik.enable=true、API 路由(Host(\traefik.dokku.me`)api@internal`)等标签。

启用 API 基础认证

建议开启 API 或 Dashboard 时同时启用基础认证。认证只作用于 API/Dashboard,不影响应用basic-auth-usernamebasic-auth-password两个属性必须同时设置,否则不生效:

dokku traefik:set --global basic-auth-username username dokku traefik:set --global basic-auth-password password

启用后需重启 Traefik 容器。实现上,用户名与密码通过htpasswd -nb生成 htpasswd 格式的认证串并写入traefik.http.middlewares.auth.basicauth.users标签(internal-functions、compose.yml.sigil)。

自定义 API 主机名

API 与 Dashboard 的默认主机名为traefik.dokku.me,可通过api-vhost属性修改:

dokku traefik:set --global api-vhost lb.dokku.me

启用后需重启 Traefik 容器。另外两个相关属性api-entry-pointapi-entry-point-address可进一步定制 API 的入口点名称与监听地址(host:port格式),设置后会在 compose 中新增独立入口点并映射端口(compose.yml.sigil)。

查看 Traefik 报告

使用traefik:report查看应用的 Traefik 配置:

dokku traefik:report
=====> node-js-app traefik information Traefik computed api enabled: false Traefik computed api vhost: traefik.dokku.me Traefik computed challenge mode: tls Traefik computed dashboard enabled: false Traefik computed http entry point: http Traefik computed https entry point: https Traefik computed image: traefik:v3.7.12 Traefik computed letsencrypt email: Traefik computed letsencrypt server: https://acme-v02.api.letsencrypt.org/directory Traefik computed log level: ERROR Traefik global api enabled: Traefik global api vhost: Traefik global challenge mode: Traefik global dashboard enabled: Traefik global http entry point: Traefik global https entry point: Traefik global image: Traefik global letsencrypt email: Traefik global letsencrypt server: Traefik global log level:

[!NOTE] 上表中的Traefik computed image已按当前仓库实际默认值标注为traefik:v3.7.12(解析自 Dockerfile),文档原示例中的traefik:v2.8为旧版本输出。

global-<prop>键保存原始全局值,未设置时为空;computed-<prop>键保存部署时实际生效的值,全局值为空时回退到内置默认值。这一“global 为空则取默认值”的逻辑在 internal-functions 的每个fn-traefik-computed-*函数中实现,与 report.go 的 computed 报告函数一一对应。

也可以针对特定应用查看:

dokku traefik:report node-js-app

还可以传入 flag 只输出某一项的值:

dokku traefik:report node-js-app --traefik-computed-api-enabled

属性速查表

可设置属性

所有 Traefik 属性均为 global-only,使用traefik:set --global <property> <value>设置。

PropertyScopeDefaultReport flagsDescription
api-enabledglobal onlyfalse--traefik-global-api-enabled,--traefik-computed-api-enabledWhentrue, enables the Traefik HTTP API
api-entry-pointglobal onlynone--traefik-global-api-entry-point,--traefik-computed-api-entry-pointName of the entry point used by the Traefik API
api-entry-point-addressglobal onlynone--traefik-global-api-entry-point-address,--traefik-computed-api-entry-point-addressAddress (host:port) the Traefik API listens on
api-vhostglobal onlytraefik.dokku.me--traefik-global-api-vhost,--traefik-computed-api-vhostVirtual host that routes to the Traefik API
basic-auth-passwordglobal onlynone--traefik-global-basic-auth-password,--traefik-computed-basic-auth-password(masked as*******in the default stdout report; the raw value is returned when queried via--format jsonor when one of these flags is requested explicitly)Password for basic auth in front of the API/dashboard
basic-auth-usernameglobal onlynone--traefik-global-basic-auth-username,--traefik-computed-basic-auth-usernameUsername for basic auth in front of the API/dashboard
challenge-modeglobal onlytls--traefik-global-challenge-mode,--traefik-computed-challenge-modeACME challenge method used by Traefik (tls,http, ordns)
dashboard-enabledglobal onlyfalse--traefik-global-dashboard-enabled,--traefik-computed-dashboard-enabledWhentrue, enables the Traefik dashboard
dns-providerglobal onlynone--traefik-global-dns-provider,--traefik-computed-dns-providerLego DNS provider name used whenchallenge-modeisdns
dns-provider-<ENV_VAR>global onlynone--traefik-global-dns-provider-<env_var>(masked as*******in the default stdout report; the raw value is returned when queried via--format jsonor when this flag is requested explicitly)Per-provider environment variables passed to the Traefik container;<ENV_VAR>is the upstream variable name (e.g.dns-provider-cloudflare-api-token)
http-entry-pointglobal onlyhttp--traefik-global-http-entry-point,--traefik-computed-http-entry-pointEntry point name handling plaintext HTTP traffic
https-entry-pointglobal onlyhttps--traefik-global-https-entry-point,--traefik-computed-https-entry-pointEntry point name handling TLS-terminated HTTPS traffic
imageglobal onlyparsed from plugins/traefik-vhosts/Dockerfile(当前为traefik:v3.7.12--traefik-global-image,--traefik-computed-imageDocker image used to run the Traefik container
letsencrypt-emailglobal onlynone--traefik-global-letsencrypt-email,--traefik-computed-letsencrypt-emailContact email enabling letsencrypt; empty disables https issuance
letsencrypt-serverglobal onlyhttps://acme-v02.api.letsencrypt.org/directory--traefik-global-letsencrypt-server,--traefik-computed-letsencrypt-serverACME directory used when requesting certificates
log-levelglobal onlyERROR--traefik-global-log-level,--traefik-computed-log-levelTraefik log level

[!NOTE]traefik:set仅接受上表中的 key 以及dns-provider-<ENV_VAR>形式的动态 key,其他 key 会被拒绝(校验逻辑见 subcommands/set)。

内部属性

以下属性不由traefik:set管理,而是由插件内部记录:

PropertyDescriptionSource
proxy-statusstarted/stoppedstate of the traefik compose projectcmd-traefik-start/cmd-traefik-stopin plugins/traefik-vhosts/command-functions

进一步探索

  • docs/networking/proxies/traefik.md:官方 Traefik 集成文档(本文的原始依据);
  • plugins/traefik-vhosts/templates/compose.yml.sigil:Traefik 容器的 compose 渲染模板,入口点、ACME、API 标签、端口与卷均在此定义;
  • plugins/traefik-vhosts/docker-args-process-deploy:部署时标签注入与健康检查转换的核心实现;
  • plugins/traefik-vhosts/internal-functions:全部 global/computed 属性的取值与默认值回退逻辑;
  • plugins/traefik-vhosts/report.go 与 plugins/traefik-vhosts/report_test.go:报告输出与凭据掩码实现及测试;
  • plugins/traefik-vhosts/Dockerfile:当前默认 Traefik 镜像版本(traefik:v3.7.12);
  • 代理相关的通用概念可参考 docs/networking/proxies 目录下的其他代理文档(nginx、Caddy、HAProxy、OpenResty、Traefik)。

【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询