Dokku 0.8.0 迁移指南:域名管理、插件卸载触发器与部署任务失败策略全解析
本文是 Dokku(A docker-powered PaaS)0.8.0 版本的迁移指南解读。0.8.0 在域名管理、插件生命周期、部署任务失败语义以及 Nginx HTTP2 支持四个方向引入了行为变更:新增 domains:set / domains:set-global 命令、引入 uninstall 插件触发器、将部署任务失败升级为"整个部署失败",并把 Nginx HTTP2 的最低版本要求提高到 1.11.5。读完本文,你将掌握这些变更的精确用法、触发条件与底层实现,能够安全地把基于 0.8.0 之前版本的部署流程迁移到新语义上。
域名管理:新增 domains:set 与 domains:set-global
0.8.0 之前,应用域名主要通过 domains:add / domains:remove 进行增量维护,操作繁琐且容易出现"先 add 再 clear"的中间态。0.8.0 引入了两个幂等语义的批量设置命令,可以直接把应用或全局域名"整体替换"为目标集合。
命令速查
完整的 domains 子命令集合(以当前仓库 docs/configuration/domains.md 为准)如下:
domains:add <app> <domain> [<domain> ...] # Add domains to app
domains:add-global <domain> [<domain> ...] # Add global domain names
domains:clear <app> # Clear all domains for app
domains:clear-global # Clear global domain names
domains:disable <app> # Disable VHOST support
domains:enable <app> # Enable VHOST support
domains:remove <app> <domain> [<domain> ...] # Remove domains from app
domains:remove-global <domain> [<domain> ...] # Remove global domain names
domains:report [<app>|--global] [<flag>] # Displays a domains report for one or more apps
domains:reset <app> # Reset app domains to global-configured domains
domains:set <app> <domain> [<domain> ...] # Set domains for app
domains:set-global <domain> [<domain> ...] # Set global domain names
其中 domains:set 与 domains:set-global 是 0.8.0 的新增能力:
# 将 node-js-app 的域名整体替换为 dokku.me 与 dokku.org
dokku domains:set node-js-app dokku.me dokku.org
# 将全局默认域名整体替换为 example.com
dokku domains:set-global example.com
底层实现:domains_set 与 VHOST 文件
从源码实现看(plugins/domains/functions),domains_set 的核心逻辑非常直接:
- 定位应用的 VHOST 文件
$DOKKU_ROOT/$APP/VHOST并touch创建; - 逐个校验传入的域名合法性(
is_valid_hostname),非法域名直接dokku_log_fail中止; - 将全部域名按换行符整体写入 VHOST 文件(覆盖旧内容,这就是"set"与"add"的本质区别);
- 如果应用当前 VHOST 处于禁用状态,会自动调用
domains_enable "$APP" --no-restart重新启用; - 触发
post-domains-update插件触发器,通知代理层(如 nginx-vhosts)重建虚拟主机配置。
对应地,domains:set-global 操作的是全局级 VHOST 配置(全局默认 TLD)。这条默认 TLD 会在初始化 Dokku 时设置,之后可用 dokku domains:add-global / domains:remove-global 增量修改,或用 domains:set-global 整体替换。该值会作为宿主机上所有应用(未显式指定域名时)的默认 domain.tld 后缀。
应用域名与全局域名的关系
Dokku 中应用主机名的默认结构为:
scheme://subdomain.domain.tld
subdomain从推送的应用名推断;domain.tld来自全局配置。
一个值得注意的行为:如果应用名本身就是一个 FQDN(例如 dokku.org),则全局虚拟主机(global virtualhost)会被忽略,该应用的 vhost URL 直接就是 dokku.org。
应用级与全局级域名可以通过 domains:report 查看(该子命令虽标注 "New as of 0.8.1",但同样是 0.8.x 系列的重要运维入口):
dokku domains:report node-js-app
=====> node-js-app domains information
Domains app enabled: true
Domains app vhosts: node-js-app.dokku.org
Domains global enabled: true
Domains global vhosts: dokku.org
也可以只取单个字段的值(便于脚本化):
dokku domains:report node-js-app --domains-app-enabled
迁移注意点:端口映射与 VHOST 开关
迁移到新命令时需注意文档中的明确警告(见 docs/configuration/domains.md):在应用部署之前添加域名会导致端口映射被提前设置。对于使用非标准端口的应用,这些端口不会被自动探测,可能引发路由问题,此时需要参考 proxy management 文档 重新配置映射。
此外,domains:disable 会覆盖应用的自定义域名(包括通过 certs:add 导入证书的域名),并丢弃 nginx 虚拟主机;作为 0.4.0 起的行为,nginx 仍会在某个随机高位端口上代理应用,以保持内部服务跨部署端口一致。需要恢复时使用:
dokku domains:enable node-js-app
dokku domains:enable --all
插件卸载:新增 uninstall 触发器
0.8.0 之前,卸载插件只是删除插件目录,插件创建的外部资源(额外容器、镜像、数据卷等)会遗留成为"孤儿资源"。0.8.0 引入了 uninstall 插件触发器,让插件在被卸载前有机会清理自身。
触发时机与调用链
从 docs/development/plugin-triggers.md 的触发器文档可知:
- 描述:用于插件"清理自身"(Cleanup after itself);
- 触发命令:
dokku plugin:uninstall; - 参数:
$PLUGIN(被卸载的插件名)。
调用链在 plugins/plugin/functions 的 uninstall_plugin() 中清晰可见:
uninstall_plugin() {
declare desc="uninstall plugin"
local PLUGIN="$1"
[[ -e $PLUGIN_CORE_AVAILABLE_PATH/$PLUGIN ]] && dokku_log_fail "Cannot uninstall a core plugin"
[[ ! -e $PLUGIN_AVAILABLE_PATH/$PLUGIN ]] && dokku_log_fail "Plugin ($PLUGIN) is not currently installed"
plugn trigger uninstall "$PLUGIN"
plugn uninstall "$PLUGIN"
dokku_log_info1_quiet "Plugin $PLUGIN uninstalled"
}
两个关键约束:
- 核心插件禁止卸载:若插件位于
PLUGIN_CORE_AVAILABLE_PATH,直接dokku_log_fail "Cannot uninstall a core plugin"; - 先触发
uninstall触发器,再执行物理卸载:plugn trigger uninstall "$PLUGIN"先行,随后才plugn uninstall删除插件目录。这意味着清理逻辑必须写在触发器文件里,才能赶在目录删除前执行。
入口命令见 plugins/plugin/subcommands/uninstall,它校验插件名非空后调用 uninstall_plugin,并刷新 bash 补全。
编写 uninstall 触发器
官方推荐的触发器实现模板(docs/development/plugin-triggers.md):
#!/usr/bin/env bash
# Cleanup up extra containers created
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
PLUGIN="$1"
[[ "$PLUGIN" = "my-plugin" ]] && docker rmi -f "${PLUGIN_IMAGE_DEPENDENCY}"
特别注意文档中的警告:务必像示例那样先校验插件名,避免误删其他插件的资源(To avoid uninstalling other plugins make sure to check the plugin name)。
迁移注意点
文档明确指出:"This functionality may be in use for newer plugins, so be aware that older Dokku versions may require manual cleanup."——即该触发器可能已被较新的插件使用(这些插件在卸载时依赖 Dokku 0.8.0+ 会调用 uninstall 触发器)。因此:
- 如果你的宿主机运行的是 0.8.0 之前的 Dokku 版本,卸载这类新插件时不会触发清理,需要手动清理残留资源(如多余容器、镜像、数据卷);
- 升级到 0.8.0+ 后,卸载行为自动获得清理保障。
部署任务:失败即中止整个部署
0.8.0 收紧了一个部署语义:只要 pre 或 post 部署任务(deployment task)中有一个失败,整个部署立即判为失败。
在此之前,部署任务的失败可能被部分容忍或仅记录日志;从 0.8.0 起失败被提升为阻断性错误。这一变更的实际影响体现在部署流水线上:
- pre-deploy 任务失败:应用不会被继续发布,部署流程中止;
- post-deploy 任务失败:虽然应用可能已经完成发布,但部署整体仍被标记为失败,便于 CI/CD 与监控体系捕获异常。
从当前仓库的事件插件来看,Dokku 的部署任务机制围绕 deployment-tasks 相关触发与 pre-deploy/post-deploy 事件展开(详见 plugins/20_events 下的 pre-deploy、post-deploy 等触发器文件),部署任务的使用与编写方法可参考 deployment-tasks 文档。
迁移注意点
- 检查现有应用是否配置了 pre/post 部署任务;若任务脚本本身会"预期性失败"(例如探活脚本在特定场景返回非零),需要修正脚本逻辑,避免 0.8.0 后整个部署被误判失败;
- 若任务失败确属可接受场景,应改用显式的成功退出(
exit 0)或在任务脚本内自行处理错误分支。
Nginx HTTP2 支持:最低版本升至 1.11.5
0.8.0 的最后一个变更与 Nginx 版本基线相关:由于 Nginx 自身的 bug,HTTP2 支持的最低版本被提高到 1.11.5。
这意味着:
- 使用 HTTP2 的应用(或依赖 nginx-vhosts 代理的站点)要求宿主机 Nginx 版本 ≥ 1.11.5;
- 低于该版本时,不应启用 HTTP2,否则可能触发上游已知缺陷;
- 迁移时请确认宿主机 Nginx 版本满足要求,或通过系统包管理升级 Nginx 后再升级到 Dokku 0.8.0。
Nginx 虚拟主机的模板与配置细节可继续参考 nginx-vhosts 插件 及其 nginx 代理文档。
迁移检查清单
综合 0.8.0 的四个变更,从旧版本升级前建议按以下清单核对:
- 域名:确认是否依赖
domains:set/domains:set-global的批量替换语义;检查应用是否在部署前设置了域名(涉及端口映射探测问题); - 插件:盘点已安装的第三方插件是否自带
uninstall触发器;若宿主机还是旧版 Dokku,提前规划手动清理方案; - 部署任务:审计所有应用的 pre/post 部署任务脚本,确保失败语义符合"失败即整个部署失败"的新规则;
- Nginx:确认版本 ≥ 1.11.5 以支持 HTTP2,必要时先升级 Nginx 再升级 Dokku。
延伸阅读
- 域名完整用法与 VHOST 开关:域名配置文档
- 端口映射调整(部署前设域名的注意事项):proxy management 文档
uninstall及其他触发器清单:plugin triggers 文档- 插件卸载入口实现:plugins/plugin/subcommands/uninstall 与 plugins/plugin/functions
- 部署任务编写指南:deployment-tasks 文档
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 StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00