Dokku DNS 配置指南:使用 A 记录与通配符域名将应用路由到你的 PaaS 服务器
【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku
导读
DNS(域名系统)是 Dokku 实现"一服务器多应用"路由的核心基础设施:Dokku 依赖 DNS 把形如node-js-app.example.tld的域名解析到服务器 IP,再结合内置的 nginx 等代理(vhost)机制将不同子域名的流量分发到对应应用。本篇指南以 Dokku 仓库中的 docs/networking/dns.md 为主体,讲解子域名(app.myserver.example.tld)与根域(app.example.tld)两种接入方案,并配合 BIND 格式的 zone 文件示例与host/dig/nslookup验证命令,帮助你在完成 安装文档 之前先打好域名解析的地基。读完本文,你将能独立完成 Dokku 服务器的域名接入配置,并理解 vhost 域名在 Dokku 内部是如何被存储与生成路由 URL 的。
DNS 在 Dokku 路由中的角色
Dokku 是一个运行在单台服务器上的开源 PaaS(Platform as a Service),应用通过git push推送后即可自动构建并运行。当一台 Dokku 服务器上同时运行多个应用时,Dokku 使用**域名(vhost)**来区分它们:如果你持有域名example.tld,并部署了node-js-app1和node-js-app2两个应用,Dokku 会分别让它们通过node-js-app1.example.tld和node-js-app2.example.tld对外提供服务。
因此,DNS 配置的正确与否直接决定了应用能否被外部访问。安装文档对此有明确说明:官方"建议为服务器至少绑定一个域名。这不是必须的,但使用域名会让应用访问更加容易"(见 docs/getting-started/installation/index.md)。绑定的方式有两种:
- 通配符域名(
*.domain.tld的 A 记录):应用可通过$APP.domain.tld访问,即每个应用自动获得形如应用名.域名的子域名。 - 单一域名(
domain.tld的 A 或 CNAME 记录):应用将通过domain.tld:$RANDOM_PORT(域名加随机端口)的形式访问。
DNS 服务器的多样性:为何以 BIND 格式为示例
DNS 生态中存在大量实现:"野生"环境里常见的 DNS 服务器包括 BIND、dnsmasq 和 PowerDNS(pdns)等;Windows 自带的 DNS 服务器之外还有 Unbound、Posadis 等选择;此外还有数以万计的托管 DNS 服务商(Managed DNS Providers),各自提供不同的配置界面。维基百科上维护着 DNS 服务器软件对比和托管 DNS 提供商清单,可以按需查阅。
正因为可选项如此之多,本文档聚焦于 DNS 本身的通用概念,并统一采用BIND 格式编写示例,以便读者将这些概念适配到自己使用的 DNS 服务器软件或托管 DNS 服务商。
前置假设
在开始之前,本文档假定你已经具备以下条件:
- 对 DNS 有基本的了解——知道 DNS 的作用是把名称(如
example.tld)转换为地址(如127.0.0.1)即可。若完全陌生,建议先阅读一篇面向开发者的 DNS 入门文章。 - 已注册一个域名,并将其指向你偏好的托管 DNS 服务商,或运行着自建的 BIND DNS 服务器。
- 已拥有一台互联网上的服务器,正打算按照 README 中的指引安装 Dokku——但先不要执行安装,因为 DNS 应该先配置好。
谨记:DNS 依赖缓存
DNS 高度依赖缓存。你对 DNS 所做的修改,可能需要几秒到几天的时间才能在全球传播生效。如果曾经访问过example.tld,之后又修改了它的 IP 记录,你的电脑可能在一段时间内仍使用旧的解析结果。因此在配置过程中,验证结果"看起来不对"时,先考虑缓存因素。
开始前的准备:获取服务器 IP
为便于说明,全文示例统一使用域名example.tld和 IP 地址127.0.0.1(实际使用时请替换为你的真实域名与服务器公网 IP)。
首先登录你的服务器,运行ifconfig或ip addr命令查看服务器的 IP 地址:
ip addr # 或 ifconfig记下这个 IP,接下来所有 DNS 记录都要指向它。
做出决策:子域名还是根域名?
拿到 IP 之后,你需要对域名策略做一个决定:希望example.tld下所有名称都指向 Dokku 服务器,还是只用一个子域来承载 Dokku?
换句话说,你的应用最终通过node-js-app.example.tld访问,还是通过node-js-app.myserver.example.tld访问?
- 子域名方案的优点是干净隔离,不会影响
example.tld根域上可能存在的其他服务; - 根域名方案则能让应用拥有最短、最直观的访问地址。
方案一:使用子域名(node-js-app.myserver.example.tld)
子域名方案最简单,配置步骤分为三步。
1. 创建子域名的 A 记录
在配置服务器时,你多半已经给它起了一个名字,例如myserver.example.tld。进入你的托管 DNS 服务商控制台,创建一个名为myserver的A 记录,值填入刚才从服务器上查到的 IP 地址。
2. 创建通配符 A 记录
仅有一个 A 记录还不够:Dokku 会为每个应用生成独立的子域名(node-js-app.myserver.example.tld、python-app.myserver.example.tld等)。为所有应用自动生效,你还需要一条通配符记录:创建一个名为*.myserver的 A 记录,值同样填入服务器 IP。通配符记录会匹配myserver.example.tld下的任意三级子域名。
如果你的托管 DNS 服务商不支持通配符记录,则需要为每个应用手动添加一条 A 记录(应用名对应主机名),这会增加后续部署新应用的维护成本。
3. BIND zone 文件示例
如果你使用 BIND,对应的 zone 文件大致如下:
$ORIGIN example.tld $TTL 5m myserver IN A 127.0.0.1 *.myserver IN A 127.0.0.1其中:
$ORIGIN example.tld声明该 zone 的根域名;$TTL 5m将记录的默认 TTL(生存时间)设为 5 分钟,控制解析结果被缓存的时间长度;- 两条 A 记录分别将
myserver.example.tld及其下的任意子域指向127.0.0.1(示例 IP,请替换为真实地址)。
4. 验证 DNS 解析
在 Linux 上,可以通过以下任一命令验证配置是否生效:
host myserver.example.tld dig -t A myserver.example.tld nslookup myserver.example.tld再次提醒:返回的结果可能是被缓存的,若与预期不符,请耐心等待或使用不同的公共 DNS 递归服务器复查。
如果一切正常,你还应该能查询myserver.example.tld下的任意其他名称,并得到同样的服务器 IP:
host test.myserver.example.tld host xyzzy.myserver.example.tld5. 验证 SSH 访问
DNS 生效后,你应该能够直接通过主机名访问服务器:
ssh root@myserver.example.tld如果 SSH 连接成功,说明 DNS 已为 Dokku 正确配置。之后即可继续执行 安装文档 中的安装步骤。
方案二:使用根域名(node-js-app.example.tld)
根域名方案与子域名方案几乎相同,区别在于:
- 主机名位于
example.tld之下,仍然需要一条A 记录(如example.tld本身,或按需添加通配符*); - 应用访问地址不再是
app.myserver.example.tld,而是app.example.tld。
原文档指出这一节仍在完善中。结合仓库中的 docs/configuration/domains.md,根域名方案的关键在于后续的全局域名配置:安装完成后,通过domains:set-global将根域名设置为所有应用的默认 TLD。Dokku 会按scheme://subdomain.domain.tld的结构为应用生成主机名,其中subdomain来自推送的应用名,domain.tld则来自全局配置。
安装后配置全局域名
安装并配置好 SSH 密钥后,用dokku domains:set-global设置你的全局域名:
# 使用你拥有的任意域名,该域名应有一条 A 记录或 CNAME 指向服务器 IP dokku domains:set-global dokku.me # 也可以直接使用服务器 IP dokku domains:set-global 10.0.0.2 # 还可以借助 sslip.io 获得子域名支持(将 .sslip.io 追加到 IP 后面) dokku domains:set-global 10.0.0.2.sslip.io这来自 docs/getting-started/installation/index.md:sslip.io这类通配 DNS 服务可以把10.0.0.2.sslip.io解析为10.0.0.2,从而在没有自有域名时也获得子域名能力,与真实域名效果一致。
设置全局域名后,部署应用即可自动获得app.你的域名的访问地址。域名管理的完整命令(如domains:add、domains:remove、domains:report等)可参阅 docs/configuration/domains.md。
源码级原理:Dokku 如何利用 DNS 区分应用
理解了操作步骤之后,从源码层面看看 Dokku 是如何把域名体系落地的,能帮助你更好地排查问题。
vhost 的存储位置
Dokku 的 domains 插件把域名(vhost)以纯文本文件形式存储:
- 全局 vhost:
$DOKKU_ROOT/VHOST(默认即/home/dokku/VHOST),由domains:set-global写入,见 plugins/domains/functions 中的domains_set_global; - 应用级 vhost:
$DOKKU_ROOT/$APP/VHOST,如/home/dokku/node-js-app/VHOST,由domains:add等命令维护,见 plugins/domains/functions 中的get_app_domains。
应用主机名的生成逻辑
当应用没有配置自己的 vhost 时,Dokku 会基于全局 vhost 推导主机名,核心逻辑在get_default_vhosts(plugins/domains/functions):
- 若全局 vhost 是 IP 地址(IPv4/IPv6),则直接跳过、不生成域名;
- 否则把应用名与 vhost 拼接:应用名不含点号时得到
应用名.全局域名,如node-js-app.example.tld; - 应用名本身就是 FQDN(含点号,如
dokku.org)时,直接以应用名作为主机名,忽略全局 vhost——这与 docs/configuration/domains.md 的描述一致; - 拼接前还会调用
nginx-hostname插件触发器,允许插件覆盖默认主机名算法。
也就是说,只要你的通配符 DNS 能把*.example.tld解析到服务器 IP,Dokku 就能把每个应用自动映射到对应子域名,这正是方案一中通配符 A 记录起作用的原理。
路由 URL 的生成
部署完成后,domains-urls等命令会生成应用的访问 URL,逻辑见 plugins/domains/internal-functions 的fn-domains-generate-url:监听端口为 80 时输出http://域名,443 且存在证书时输出https://域名,其他情况输出scheme://域名:端口。
vhost 开关:NO_VHOST
每个应用都可以通过NO_VHOST环境变量控制是否启用 vhost:is_app_vhost_enabled读取该变量,值为1时 vhost 功能关闭(见 plugins/domains/functions)。对应地,dokku domains:disable <app>与dokku domains:enable <app>会设置/清除该变量。关闭 vhost 后,nginx 不再为应用生成虚拟主机,但应用仍会绑定在某个随机高位端口上供内部访问——这类内部服务不需要 DNS 记录。
代理层对未知域名的兜底
即便 DNS 配置无误,也可能有流量访问到未匹配任何应用的域名。对于默认的 nginx 代理,Dokku 在安装时会配置一个 catch-all 默认站点(/etc/nginx/conf.d/00-default-vhost.conf):对没有匹配任何应用的 HTTP 请求返回444(直接关闭连接),HTTPS 则使用ssl_reject_handshake拒绝握手。详细行为参见 docs/networking/proxies/nginx.md。
常见问题与排查提示
- 解析迟迟不生效:优先怀疑 DNS 缓存。检查
dig结果中的 TTL,并用dig @8.8.8.8 你的域名之类的命令绕过本地缓存直接查询权威服务器。 - 通配符记录被拒绝:部分托管 DNS 服务商对通配符有特殊限制,可改用为每个应用逐一添加 A 记录的方式,或联系服务商确认支持情况。
- 访问返回 444 / 连接被重置:说明请求到达了 nginx 但未匹配到任何应用 vhost,检查
dokku domains:report <app>确认应用的 vhost 是否已正确生成,且 DNS 记录指向的确实是 Dokku 服务器 IP。 - 应用显示为
域名:随机端口:说明你的域名策略是单一域名(非通配符)。若希望按子域名访问,需要配置通配符 A 记录,并通过dokku domains:set-global设置全局域名,详见 docs/configuration/domains.md。
小结
DNS 是 Dokku 多应用路由体系的地基:一条指向服务器 IP 的 A 记录让 Dokku 主机本身可达,一条通配符 A 记录则让每个新部署的应用自动获得独立子域名。本文以 BIND 格式给出了可直接套用的 zone 文件示例,并提供了host、dig、nslookup等验证手段;同时从 plugins/domains/functions 的源码出发,解释了 vhost 的存储位置、主机名生成逻辑与 URL 拼接规则。在完成 安装文档 后,记得用dokku domains:set-global写入全局域名,你的 Dokku 服务器即可按子域名对外提供应用服务了。
【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考