首页
/ Dokku 代理管理完全指南:从 nginx 切换到 Caddy/HAProxy/Traefik 与代理配置的深入解析

Dokku 代理管理完全指南:从 nginx 切换到 Caddy/HAProxy/Traefik 与代理配置的深入解析

2026-09-09 12:30:06作者:宣利权Counsellor

导读

本文以 Dokku 的 proxy 插件(核心命令与属性体系)为主线,系统讲解如何在 Dokku PaaS 中切换、启用/禁用、重建与清理应用代理配置,并深入到端口映射、容器网络绑定、代理实现插件编写等进阶话题。读完本文,你将掌握 proxy:setproxy:build-configproxy:clear-configproxy:report 等命令的完整用法与属性取值规则,理解"应用级 → 全局级 → 内置默认"三级取值优先级背后的源码实现,并能独立排查与修复应用代理配置漂移问题。


一、背景:为什么需要独立的 Proxy 插件

Dokku 0.5.0 之前,端口代理逻辑耦合在 nginx-vhosts 插件内部。Dokku 0.5.0 将端口代理从 nginx-vhosts 插件中解耦出来,独立成 proxy 插件;Dokku 0.6.0 又引入将宿主机端口映射到具体容器端口的能力。这一架构变化的意义在于:代理实现不再被 nginx 绑定,HAProxy、Caddy、Traefik、OpenResty 等代理软件都可以作为 nginx 的替代品接入 Dokku。

在仓库中,proxy 插件的核心实现在 plugins/proxy/proxy.go,其 DefaultProperties 定义了全部可设置属性及其默认值:

DefaultProperties = map[string]string{
    "disabled":       "false",
    "proxy-port":     "",
    "proxy-ssl-port": "",
    "type":           "",
}

其中 type 为空字符串即代表"未显式设置",实际生效时会回退到内置默认值 nginx(详见后文"取值优先级")。插件版本号可在 plugins/proxy/plugin.toml 中查看。

proxy 插件的完整命令一览(新版命令,自 0.5.0 引入、0.6.0 增强):

proxy:build-config [--parallel count] [--all|<app>] # (Re)builds config for given app
proxy:clear-config [--all|<app>] # Clears config for given app
proxy:disable [--parallel count] [--all|<app>]      # Disable proxy for app
proxy:enable [--parallel count] [--all|<app>]       # Enable proxy for app
proxy:report [<app>] [<flag>]                       # Displays a proxy report for one or more apps
proxy:set [<app>|--global] <key> (<value>)          # Set or clear a proxy property for an app

二、切换代理实现(proxy:set)

2.1 按应用切换

Dokku 默认随附的代理是 nginx,可以通过 proxy:set 命令修改:

dokku proxy:set node-js-app type caddy

输出:

=====> Setting type to caddy

从源码看,CommandSet(见 plugins/proxy/subcommands.go)还保留了一个向后兼容的快捷写法:proxy:set <app> <proxy-type> 会被自动解释为 proxy:set <app> type <proxy-type>。也就是说下面的命令与上面的完全等价:

dokku proxy:set node-js-app caddy

源码中对应的兼容逻辑为:当传入的"属性名"不在 DefaultProperties 中且没有值(value == "")时,把该参数当作 type 的值处理。同时该逻辑还会做一次防护:如果参数中含有 :(疑似端口映射,例如 5000:5000),会报错提示改用 ports:set 命令:

if strings.Contains(property, ":") {
    common.LogWarn("Detected potential port mapping instead of proxy type")
    return errors.New("Consider using ports:set command or specifying a valid proxy")
}

2.2 全局切换

代理也可以全局设置。通常更推荐全局设置,因为在同一台 Dokku 主机上同时运行多个代理实现可能引发端口冲突

dokku proxy:set --global type caddy

输出:

=====> Setting type to caddy

需要特别注意:切换代理并不会自动停止或启动任何代理实现。具体的启停流程需要参考你所选代理插件的文档(例如切换为 caddy 后,需要自行处理 caddy 服务的安装与启动)。

2.3 恢复默认值

将某个属性设置为空值即可恢复默认。例如恢复 type 的默认值(即回退到全局值,最终回退到 nginx):

dokku proxy:set node-js-app type

该行为由 common.CommandPropertySet 统一实现:传入空值即删除该属性记录,后续读取时回退到上一级。


三、禁用与启用代理(proxy:disable / proxy:enable)

代理可以按应用粒度禁用。禁用后,不会为应用生成任何代理配置,进入的请求也不会经过配置的代理路由

dokku proxy:disable node-js-app

输出:

-----> Disabling proxy for app

重新启用:

dokku proxy:enable node-js-app

输出:

-----> Enabling proxy for app

这两个命令同样支持 --all--parallel 参数,可批量操作(见 plugins/proxy/src/subcommands/subcommands.go 中的 proxy:disable / proxy:enable 分支)。

从源码看,禁用/启用的核心是读写 disabled 属性(plugins/proxy/proxy.go):

  • Disable:先通过 IsAppProxyEnabled 判断,已禁用则直接返回;否则写入 disabled=true,随后触发 proxy-disable 钩子。
  • Enable:删除 disabled 属性(回到默认 false),随后触发 proxy-enable 钩子。
  • IsAppProxyEnabled:读取 disabled 属性,默认值为 false,即"只要不是显式 true 就视为启用"。

在 nginx 实现中,proxy-disable 触发钩子(见 plugins/nginx-vhosts/proxy-disable)会进一步调用 domains-disable 并重启应用,从而让应用不再通过 nginx 暴露。


四、设置代理端口(proxy-port / proxy-ssl-port)

当应用的域名被禁用(参见 域名配置文档)时,Dokku 仍会把应用暴露在一个高位端口上,以便内部服务在多次部署间通过稳定端口访问应用。用于此目的的非 SSL 与 SSL 端口可通过 proxy:set 配置:

dokku proxy:set node-js-app proxy-port 5000
dokku proxy:set node-js-app proxy-ssl-port 5443

这两个属性同样支持全局设置,应用级值优先于全局值

dokku proxy:set --global proxy-port 5000
dokku proxy:set --global proxy-ssl-port 5443

恢复默认值(清空):

dokku proxy:set node-js-app proxy-port

plugins/proxy/proxy.goGlobalProperties 中可以看到,proxy-portproxy-ssl-porttype 三个属性允许全局作用域,而 disabled 仅限应用级:

GlobalProperties = map[string]bool{
    "proxy-port":     true,
    "proxy-ssl-port": true,
    "type":           true,
}

proxy-port / proxy-ssl-port 的值最终会进入代理配置模板,作为生成的 nginx(或其他代理)配置中的 HTTP/HTTPS 监听端口(在 nginx 模板变量中对应 {{ .PROXY_PORT }}{{ .PROXY_SSL_PORT }},见 nginx 代理文档 的"可用模板变量"一节)。

关于 Dokku 使用的端口映射方案,请参见 端口管理文档 中的 端口方案(Port Scheme) 一节;应用端口映射的具体管理方式见 端口管理文档


五、重建代理配置(proxy:build-config)

某些情况下,应用的代理配置可能与应用的实际状态发生漂移(例如 web 容器重启后 IP 变化、手动编辑过配置等)。此时可随时用 proxy:build-config 重建配置。该命令会为给定应用触发当前代理实现(默认 nginx)的重建;如果应用当前没有 web 监听器,命令可能失败

dokku proxy:build-config node-js-app

使用 --all 标志可重建所有应用的代理配置:

dokku proxy:build-config --all

默认情况下,批量重建是串行执行的,可通过 --parallel 控制并行度:

dokku proxy:build-config --all --parallel 2

--parallel 设为 -1 时,并行 worker 数会自动取为当前机器的 CPU 核数:

dokku proxy:build-config --all --parallel -1

源码佐证:在 plugins/proxy/src/subcommands/subcommands.go 中,--parallel 的默认值取自 proxy.RunInSerial(常量值为 0,见 plugins/proxy/proxy.go),即默认串行;-1 表示按 CPU 数匹配。批量操作通过 common.RunCommandAgainstAllApps 实现。

从 nginx 实现的触发钩子(plugins/nginx-vhosts/proxy-build-config)可以看到完整的执行链路:先通过 proxy-type 触发器确认应用使用的是 nginx(若不是则直接返回,避免干扰其他代理实现),再检查是否存在网络配置;若存在则先触发 network-build-config 重建网络配置,再调用 nginx_build_config 生成 nginx 配置,最后处理模板文件的原子替换与清理。


六、清理生成的代理配置(proxy:clear-config)

[!IMPORTANT] 自 0.27.0 引入

生成的代理配置也可以用 proxy:clear-config 命令清理:

dokku proxy:clear-config node-js-app

使用 --all 可清理所有应用:

dokku proxy:clear-config --all

清理代理配置的效果取决于当前使用的代理插件,具体行为请查阅对应代理实现的文档。以 nginx 为例,plugins/nginx-vhosts/proxy-clear-config 中先确认应用使用的是 nginx,然后触发 network-clear-config 并调用 nginx_clear_config 删除生成的 nginx 配置文件;--all 模式则遍历所有应用逐个清理,并汇总退出码。


七、查看代理报告(proxy:report)

[!IMPORTANT] 自 0.8.1 引入

使用 proxy:report 可以查看应用当前的代理状态报告:

dokku proxy:report

输出示例:

=====> node-js-app proxy information
       Proxy computed type: nginx
       Proxy enabled:       true
       Proxy global type:
       Proxy type:
=====> python-sample proxy information
       Proxy computed type: nginx
       Proxy enabled:       true
       Proxy global type:
       Proxy type:
=====> ruby-sample proxy information
       Proxy computed type: nginx
       Proxy enabled:       true
       Proxy global type:
       Proxy type:

字段含义如下:

  • typeglobal-type 分别保存原始的应用级值与全局值,未设置时为空;
  • computed-type 保存部署时实际生效的值:优先取应用级值,未设置则回退到全局值,再未设置则回退到内置默认 nginx

针对单个应用:

dokku proxy:report node-js-app

输出:

=====> node-js-app proxy information
       Proxy computed type: nginx
       Proxy enabled:       true
       Proxy global type:
       Proxy type:

也可以传标志只输出某一项信息:

dokku proxy:report node-js-app --proxy-computed-type

从源码看,computed-type 的三级回退逻辑实现在 plugins/proxy/functions.gogetComputedProxyType 中:先读应用级 type,为空再读全局 type,仍为空则返回 "nginx"proxy-portproxy-ssl-portdisabled 等属性也遵循同样的"应用级 → 全局级 → 默认值"回退模式(对应 getComputedProxyPortgetComputedProxySSLPortgetComputedDisabled)。proxy:report 支持的全部标志在 plugins/proxy/report.go 中定义,例如 --proxy-type--proxy-global-type--proxy-computed-type--proxy-enabled--proxy-disabled--proxy-proxy-port--proxy-global-proxy-port--proxy-computed-proxy-port 等。

另外 proxy:report 还支持 --format json(由 plugins/proxy/src/subcommands/subcommands.go 中的 --format 标志解析,取值 stdoutjson),便于自动化脚本解析。JSON 输出的键为去掉 --proxy- 前缀后的名称(如 typeglobal-typecomputed-type);在 0.38.x 的弃用窗口期内还会额外输出带 proxy- 前缀的旧键(如 proxy-type),这些旧键将在未来的主版本中移除。

7.1 容器网络接口绑定(历史行为变更)

自 0.11.0 起行为变更

在 Dokku 0.5.00.11.0 之间,启用或禁用应用的代理同时会控制应用是否绑定到所有网络接口(例如 0.0.0.0)。自 0.11.0 起,这一行为改由 network 插件控制。详见 网络文档中的容器网络接口绑定 一节。


八、属性参考(Properties)

8.1 可设置属性

[!NOTE] Report flags 列是 proxy:report 接受的 CLI 参数名。proxy:report --format json 输出的 JSON 键为去掉 --proxy- 前缀后的同名(如 typeglobal-typecomputed-type)。带 proxy- 前缀的旧键(如 proxy-type)在 0.38.x 弃用窗口期内仍会输出,将在未来主版本移除。

属性 作用域 默认值 报告标志 说明
disabled 仅应用级 false --proxy-disabled--proxy-computed-disabled(同时以反转形式暴露为 --proxy-enabled true 时禁用该应用的代理集成(proxy:enable / proxy:disable 即读写此属性)
proxy-port 应用 + 全局 --proxy-proxy-port--proxy-global-proxy-port--proxy-computed-proxy-port 覆盖生成的代理配置中 HTTP 监听端口
proxy-ssl-port 应用 + 全局 --proxy-proxy-ssl-port--proxy-global-proxy-ssl-port--proxy-computed-proxy-ssl-port 覆盖生成的代理配置中 HTTPS 监听端口
type 应用 + 全局 nginx --proxy-type--proxy-global-type--proxy-computed-type 处理应用流量的代理实现(nginxcaddyhaproxytraefikopenresty 或自定义插件)

8.2 只读标志

以下标志会出现在 proxy:report 输出中,但不由 proxy:set 管理

标志 说明
--proxy-enabled 当应用的 disabled 属性不为 true 时输出 true

九、实现一个自定义代理插件

自定义插件名必须-vhosts 后缀结尾,否则通过 proxy:set 进行切换可能无法按预期工作。

以下 Dokku 命令用于与完整的代理实现交互,每个命令都对应相应的插件触发钩子:

命令 触发钩子
domains:add:为应用添加域名 post-domains-update
domains:clear:清空应用的域名 post-domains-update
domains:disable:禁用应用域名 pre-disable-vhost
domains:enable:启用应用域名 pre-enable-vhost
domains:remove:从应用移除域名 post-domains-update
domains:reset:将应用域名重置为全局配置的域名 post-domains-update
domains:set:设置应用的全部域名 post-domains-update
proxy:build-config:构建(或重建)外部代理配置 proxy-build-config
proxy:clear-config:清理外部代理配置 proxy-clear-config
proxy:disable:禁用应用的代理配置 proxy-disable
proxy:enable:启用应用的代理配置 proxy-enable
ports:add:为应用添加一个或多个端口映射 post-proxy-ports-update
ports:clear:清空应用的全部端口映射 post-proxy-ports-update
ports:remove:从应用移除一个或多个端口映射 post-proxy-ports-update
ports:set:设置应用的全部端口映射 post-proxy-ports-update

代理实现可以根据需要省略部分功能,或者使用插件触发钩子从其他插件补充配置信息。此外:

  • 单个代理实现可能触发应用重建,具体取决于代理元数据在代理实现中的暴露方式;
  • 代理实现可以以任何合适的方式安装代理本身所需的额外软件——代理软件既可以运行在宿主机上,也可以运行在 Docker 容器中(通过暴露端口或使用宿主机网络)。

以 nginx 实现为参照:其 proxy-build-configproxy-clear-configproxy-disable 等触发钩子均会先通过 proxy-type 触发器校验应用使用的代理类型是否为 nginx,再执行相应动作(见 plugins/nginx-vhosts 目录下的同名文件),这种"类型校验 + 委托执行"的写法是编写自定义代理插件的良好范本。


十、深入 nginx 实现:代理配置的生成与生命周期

虽然 proxy 插件负责抽象与调度,但默认的 nginx 实现承载了绝大多数实际流量,理解其内部行为有助于排查代理相关问题。完整内容参见 nginx 代理文档,以下是与 proxy 插件直接相关的要点。

10.1 请求代理与负载均衡

默认情况下,只有 web 进程会被 nginx 代理实现转发。nginx 以**轮询(round-robin)**方式将请求分发到所有已部署(已扩容)的运行 web 进程类型的容器上,从而让宿主机资源在单线程应用中得以充分利用(例如在 4 核机器上执行 dokku ps:scale node-js-app web=4)。

[!NOTE] 由于插件的实现方式,如果应用成功启动了 web 容器但其他容器部署失败,nginx 最终可能停止路由请求。此时应回滚代码,或手动执行 dokku proxy:build-config $APP 以确保请求路由到新的 web 容器。

10.2 未部署应用的 nginx 配置(自 0.38.0)

当应用已创建但尚未部署、没有 web 进程类型、或没有运行中的 web 进程时,Dokku 会生成一个返回 502 Bad Gateway 的最小化 nginx 配置,以确保:

  • 应用的域名可解析并返回非 200 状态码,便于监控工具发现问题;
  • 诸如 letsencrypt 之类的 SSL 证书签发工具可以正常工作(因为 nginx 已在监听该域名);
  • nginx.conf.d/ 包含目录可用于插件自定义。

该 502 错误页内置了自动重试的 JavaScript,应用可用时会自动刷新页面。一旦应用部署完成且有运行中的 web 进程,占位配置会被自动替换为完整代理配置。

10.3 自定义 nginx 配置(nginx.conf.sigil)

Dokku 使用名为 sigil 的模板库为每个应用生成 nginx 配置。可以提交一份名为 nginx.conf.sigil 的文件(内容基于 默认配置模板)来覆盖默认模板。模板查找位置取决于部署方式:

  • git:from-imagegit:load-image 部署:Docker 镜像的 WORKDIR
  • 其他所有部署(git push、git:from-archivegit:sync):源码树根目录。

如需为单个应用指定其他路径(例如 monorepo 场景),可用 nginx:set 设置 nginx-conf-sigil-path(相对路径,不会按绝对路径处理;若仓库中不存在该文件,则按"无 nginx.conf.sigil"继续构建):

dokku nginx:set node-js-app nginx-conf-sigil-path .dokku/nginx.conf.sigil

模板中可用的变量包括:{{ .APP }}(应用名)、{{ .PROXY_PORT }}(非 SSL 监听端口,与 proxy-port 属性一致)、{{ .PROXY_SSL_PORT }}(SSL 监听端口,与 proxy-ssl-port 属性一致)、{{ .PROXY_PORT_MAP }}(端口映射列表)、{{ .PROXY_UPSTREAM_PORTS }}(上游端口列表)、{{ .SSL_INUSE }}{{ .NOSSL_SERVER_NAME }}{{ .SSL_SERVER_NAME }} 等。每个进程类型的网络监听器还会以 .DOKKU_APP_${PROCESS_TYPE}_LISTENERS 变量暴露(PROCESS_TYPE 大写化、连字符转下划线),可用于通过 nginx 暴露非 web 进程。应用环境变量则可通过 {{ var "FOO" }} 形式在模板中访问。

自定义 nginx.conf.sigil 会在每次部署开始时、模板从源码树提取后、构建阶段之前被自动预校验:模板经 sigil 渲染后,套上最小包装配置运行 nginx -t;校验失败则在整个构建工作开始前中止部署。可通过设置 disable-custom-config true 跳过此行为。注意:校验用包装配置不含全局 nginx 配置中的顶层 load_module 指令,因此依赖动态加载模块指令的 nginx.conf.sigil 即使对真实服务器配置 nginx -t 能通过,也可能在此预校验中失败;可参考 nginx-conf-sigil 文档中的自定义 nginx 模块 通过 nginx-app-template-source 触发钩子的 validate-config 模板类型提供自定义校验包装。

10.4 属性变更后记得重建配置

nginx 插件的全部属性(client-max-body-sizeproxy-read-timeouthstsx-forwarded-* 系列等)都支持应用级与全局级设置,取值优先级为"应用级 → 全局级 → Dokku 默认值"。修改这些值后都需要通过 proxy:build-config 命令重建 nginx 配置才能生效(例如修改 access-log-pathclient-max-body-size 等属性时)。nginx 插件完整属性表参见 nginx 代理文档的 Properties 一节

[!WARNING] nginx 插件不对属性值做校验,值会原样用于生成的配置中,设置时需自行保证合法性。

10.5 nginx 服务生命周期管理(0.28.0+)

  • dokku nginx:start:启动 nginx 服务(自 0.28.0);
  • dokku nginx:stop:停止 nginx 服务(自 0.28.0);
  • dokku nginx:reload:校验当前 nginx 配置并在合法时触发优雅 reload(自 0.38.0),是直接编辑 /etc/nginx/conf.d/ 下文件后的首选命令;配置非法时命令以非零退出码结束并打印校验错误,不执行 reload;
  • dokku nginx:access-logs <app> [-t] / dokku nginx:error-logs <app> [-t]:查看(-t 跟随)应用访问/错误日志,默认路径为 /var/log/nginx/${APP}-access.log/var/log/nginx/${APP}-error.log
  • dokku nginx:show-config <app>:显示应用的 nginx 配置,便于调试;
  • dokku nginx:validate-config [<app>] [--clean]:逐个校验应用 nginx 配置(基于 nginx -t);--clean 会删除无效配置。该命令的退出码为对服务器真实 nginx 配置执行 nginx -t 的退出码。

10.6 默认站点(catch-all,自 0.38.0)

在全新 apt 安装中,Dokku 会在 /etc/nginx/conf.d/00-default-vhost.conf 放置一个捕获所有未知 Host 头的默认站点:HTTPS 使用 ssl_reject_handshake on 拒绝握手,HTTP 使用 return 444 直接关闭连接。00- 前缀保证该文件先于 /etc/nginx/conf.d/dokku.conf 加载,从而让各端口的 default_server 标记在任何应用 server 块之前生效。在 nginx 版本低于 1.19.4 的系统(如随 Debian Bullseye 提供的 nginx 1.18.0)上,postinst 会检测并安装仅 HTTP 的变体。若上游 nginx 自带默认 vhost 与 Dokku 的 catch-all 冲突,postinst 会将其重命名为 ${path}.dokku-disabled 而非删除,保留本地定制内容。安装时可通过 debconf 选择不安装(echo 'dokku dokku/install_default_site boolean false' | debconf-set-selections),或安装后编辑该文件并 dokku nginx:reload 自定义行为(例如将 return 444; 改为 return 410;)。


十一、关联资源导航

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525