Dokku 版本发布历史与变更日志深度解析:从 0.38.x 安全修复到 0.1.0 初版演进
Dokku 是一款基于 Docker 的、可扩展的开源 PaaS(Platform as a Service),用于在单台服务器上构建并管理应用的生命周期。本文以仓库根目录下 HISTORY.md 这份长达 10416 行的变更日志为骨架,系统梳理 Dokku 从 0.1.0(2013-06-15 首发)到当前 0.38.27 的版本演进脉络,重点剖析 0.38.x 补丁系列中的安全修复、k3s 调度器与存储插件等新特性,并结合仓库内的发布脚本、迁移指南与构建配置,帮助读者理解 Dokku 的发布流程、版本化策略以及每个版本背后的真实改动。
一、HISTORY.md 是什么:Dokku 的官方发布记录
HISTORY.md 是 Dokku 仓库中与 README、HISTORY 并列的核心元文档,记录了项目每一个正式发布版本(截至当前共 344 个 ## x.y.z 版本小节)的安装方式与变更条目。其结构高度规范化,每个版本小节均遵循固定模板:
- 安装/升级脚本:给出基于
bootstrap.sh的安装命令,用于安装或升级到指定版本; - 分类变更列表:按
Security、Backwards Compatibility Breaks、Bug Fixes、New Features、Removals、Deprecations、Refactors、Documentation、Tests、Dependencies、Other等类别,以- #PR号: @贡献者 描述的格式罗列每个合并的 Pull Request; - 迁移指南链接:重大版本(如 0.38.0)会附带指向 docs/appendices/0.38.0-migration-guide.md 的迁移说明。
1.1 历史跨度与版本策略
HISTORY.md 的末尾(第 10410 行)记录了项目起点:
- 0.1.0(2013-06-15)首次发布,当时的能力包括:面向 Ubuntu 系统的引导脚本、基于 git 的推送与部署、基于 Nginx 的主机名支持,以及 Java、Ruby、Node.js 的 buildpack 支持。
从 0.1.0 到 0.38.27,Dokku 经历了从纯 Bash + Buildpack 起步,到 Go 插件化、多调度器(docker-local 与 k3s)、多代理(nginx/openresty/caddy/haproxy/traefik)、多构建器(herokuish/nixpacks/pack/railpack/dockerfile/lambda)的完整演进。按 docs/development/release-process.md 的说明,Dokku 遵循 semver 语义化版本规范,且在其达到稳定版(1.0)之前,破坏性变更只要求 minor 版本号递增,其余变更仅需 patch 版本号递增。
二、发布流程与 HISTORY.md 的生成机制
HISTORY.md 并非手工维护,而是由发布脚本自动生成。仓库根目录下的 contrib/release-dokku(共 476 行 Bash 脚本)实现了完整的发布流水线,其中 fn-repo-update-history-and-commit() 函数(第 249-381 行)就是 HISTORY.md 的自动生成器。
2.1 发布触发方式
根据 docs/development/release-process.md 与脚本 main()(第 413-475 行),一次发布的启动方式为:
export PACKAGECLOUD_TOKEN=SOME_TOKEN
# 支持 major / minor / patch / betafish 四种发布级别
contrib/release-dokku
脚本会依次完成以下动作:
- 从 debian/control 读取当前版本号(
fn-version-current,第 94-98 行); - 按发布级别计算下一个版本号(
fn-version-next,第 100-125 行):major递增主版本并清零 minor/patch,minor递增次版本并清零 patch,patch仅递增 patch,build则生成当前版本build+短提交号形式; - 遍历 plugins/*/plugin.toml 等文件执行版本号替换(
fn-repo-update,第 206-247 行); - 通过 GitHub API 拉取自上一版本以来合并的 Pull Request,并按 label 中的
type归类到 Security/Bug/Enhancement/Dependencies 等桶中(第 259-305 行); - 按照固定的章节顺序(Security → BC Breaks → Bug Fixes → New Features → Removals → Deprecations → Refactors → Documentation → Tests → Dependencies → Other)把各桶拼接成新版本小节,插入 HISTORY.md 顶部并提交(第 307-381 行);
- 构建并提取 amd64/arm64 的 deb 包,发布到 packagecloud,构建多架构 Docker 镜像,最后推送 git tag。
也就是说,读者在 HISTORY.md 中看到的每一条 - #8933: @josegonzalez Do not require a local image for k3s deploys,其格式 - #PR号: @作者 标题 正是由脚本第 278 行 CHANGELOG_TEXT="- #${PULL_REQUEST_ID}: @${AUTHOR} ${TITLE}" 直接生成的,标题取自 PR 标题,作者取自 PR 提交者。
2.2 版本小节的固定模板
脚本第 307-313 行生成的版本小节头部,与 HISTORY.md 中每个版本的模板完全一致:
# History
## ${NEXT_VERSION}
Install/update via the bootstrap script:
```shell
wget -NP . https://dokku.com/install/v${NEXT_VERSION}/bootstrap.sh
sudo DOKKU_TAG=v${NEXT_VERSION} bash bootstrap.sh
若对应的迁移指南文件 docs/appendices/${NEXT_VERSION}-migration-guide.md 存在,还会追加一行 "See the [x.y.z migration guide]..." 链接(第 315-317 行)。这正是 0.38.0 小节引用迁移指南、而绝大多数 patch 版本没有迁移指南的原因。
三、0.38.x 补丁系列解析:安全、调度器与存储的密集迭代
当前仓库 HEAD 版本为 0.38.27(见 debian/control 第 2 行 Version: 0.38.27)。0.38.x 系列展示了 Dokku 在 patch 级别上快速迭代的典型节奏,其中 0.38.0 是功能集大版本,0.38.1 起为补丁系列。
3.1 0.38.0:功能集大版本
0.38.0 小节位于 HISTORY.md 第 782-845 行,是本系列最重要的里程碑,包含多项结构性改动:
- 构建记录跟踪(#3697):将 builds 插件迁移到 Go 并跟踪每次构建记录;
- ENV 文件统一(#6716):将 app 与全局 ENV 文件迁移到统一配置路径;
- app.json 增强(#8157、#8259):支持通过 app.json 指定 buildpacks 与 post-create 环境变量;
- Docker 选项作用域(#8516):docker-options 可限定到特定 Procfile 进程;
- k3s 基础设施升级(#8402、#8403、#8404):升级 keda 至 2.19.0、ingress-nginx chart 至 4.15.1、vector chart 至 0.52.0;
- 命名存储条目(#8538):新增调度器感知的命名存储条目;
- 部署时立即发送 SIGTERM(#8517):部署成功后立即向旧容器发送 SIGTERM,配合 docs/deployment/zero-downtime-deploys.md 中的
wait-to-retire机制实现优雅停机; - 默认开启 live-restore(#8154):安装 Dokku 时默认启用 Docker live-restore;
- 为无 web 监听器的应用生成 502 配置(#8493)。
这些改动的影响面在 docs/appendices/0.38.0-migration-guide.md 中有详细说明,例如:Dokku 现在会为没有运行 web 进程的应用生成返回 502 的最小 nginx 配置;自定义 nginx.conf.sigil 模板中 DOKKU_APP_WEB_LISTENERS 变量可能为空,模板需使用条件渲染兜底。
3.2 安全修复贯穿补丁系列
0.38.x 补丁系列中,安全问题被单列为 Security 章节,体现了官方对供应链与命令注入攻击的持续加固:
| 版本 | PR | 修复内容 |
|---|---|---|
| 0.38.2 | #8590 | 限制应用名称以防命令注入 |
| 0.38.2 | #8591 | 加固归档解压以防符号链接穿越 |
| 0.38.2 | #8589 | 强制 .netrc 凭据文件权限为 0600 |
| 0.38.2 | #8588 | 清理 openresty include 文件名以防 eval 注入 |
| 0.38.7 | #8672 | 防止 app.json cron 命令造成宿主 shell 注入 |
| 0.38.25 | #8848 | 防止 docker options eval 造成命令注入 |
其中 #8848 的行为变化在 docs/appendices/0.38.0-migration-guide.md 第 29 条有详细描述:通过 docker options、dokku run 的 -e/--env 标志以及 --ttl-seconds 提供的值,不再由 shell 求值,而是按 token 原样传递,从而封堵 $(...)、反引号等表达式在宿主以 dokku 用户身份执行的安全漏洞;--ttl-seconds 因此必须为纯整数。
3.3 k3s 调度器成为重点迭代方向
从 HISTORY.md 0.38.x 小节看,scheduler-k3s(仓库内对应 plugins/scheduler-k3s,含 44 个 Go 源文件与 31 个 YAML 模板)是补丁系列中最活跃的模块:
- 0.38.6:#8668 将 cron-id 标签哈希化以适配 Kubernetes 63 字节标签上限;
- 0.38.8:#8692 为 scheduler-k3s 场景下的 traefik 启用压缩中间件;
- 0.38.12-0.38.15:chart overrides、annotations、labels 改为以 JSON map 持久化(#8718、#8720),并新增
scheduler-k3s:charts:set、:charts:report、annotations:report、labels:report子命令(#8715、#8716); - 0.38.17:#8729 新增
scheduler-k3s:preview子命令,用于预览 Helm chart 变更; - 0.38.25:#8849 支持 k3s 上按应用配置 letsencrypt 邮箱;
- 0.38.26:#8909、#8911 支持手动管理的证书签发者(cert issuer)以及通配符域名经 traefik 路由;
- 0.38.27:#8933 不再要求 k3s 部署必须有本地镜像。
同时 0.38.x 系列在 plugins/scheduler-k3s/go.mod 层面持续跟进 cert-manager、keda、helm、k8s.io 各组件版本,反映其与 Kubernetes 生态保持同步的节奏。
3.4 存储插件的命名资源化改造
0.38.0 引入的命名存储条目(#8538)在补丁系列中继续演进,相关改动集中在 plugins/storage(含 20 个 Go 文件):
- 0.38.9:#8697 将 openresty report 拆分为 raw/computed/global(存储插件同批改造);
- 0.38.10:#8702
storage:destroy增加二次确认提示; - 0.38.11:#8704 修复 chown 存储目录时传入条目 basename;
- 0.38.12:#8711
storage:mount新增--volume-options标志; - 0.38.13:#8712、#8714 在
storage:list json中暴露 readonly 与 volume_options 字段,并在storage:report中暴露每个挂载点的明细;#8713 使storage:mount对已存在的挂载执行 upsert; - 0.38.27:#8920 新增存储目录模式与删除标志。
按 docs/appendices/0.38.0-migration-guide.md 第 33 条的说明,持久卷现在通过 storage:create、storage:mount、storage:set、storage:destroy 作为命名、调度器感知的一等资源管理;旧的 storage:mount <app> <host>:<container> 冒号形式在 docker-local 上仍可用但已弃用,在 k3s 上会被拒绝;条目名必须符合 DNS-1123 标签规范且不超过 45 个字符,以便直接用作 Helm release 与 Kubernetes 资源名。
四、全局 report 体系重构:raw/computed/global 三态约定
0.38.x 系列中另一个贯穿性的工程改造,是 :report 子命令输出体系的规范化。相关条目在 HISTORY.md 中反复出现:
- 0.38.0:#8527 让所有
:report子命令接受--global; - 0.38.3:#8599 为 Dokku 容器本身增加 Docker healthcheck;#8601 重命名 app-json:report 标志;
- 0.38.4:#8614 拆分 scheduler-docker-local report;
- 0.38.5:#8626 拆分 caddy report 的 tls-internal 为 raw/computed/global;
- 0.38.6:#8640、#8664、#8668 拆分更多全局键,并把文件系统迁移标记转为插件属性;
- 0.38.7:#8678、#8679、#8680 对齐 ps/cron/openresty report 键;
- 0.38.8:#8688、#8691、#8689、#8690 继续补齐可设置属性与 JSON 键对齐;
- 0.38.9:#8697 拆分 openresty report;
- 0.38.12:#8706 使 apps:set/apps:report 与 Dokku 实际读取的键对齐;
- 0.38.26:#8856 在
ports:report json中加入预解析的port_mappings。
按 docs/appendices/0.38.0-migration-guide.md 第 24-27 条的权威解释:
- 形如
<plugin>-global-<property>的键现在返回原始存储的全局值(从未设置则为空); - 新增
<plugin>-computed-<property>键返回生效值(依次回退:应用值 → 全局值 → 内置默认值); - 所有 Go 实现的插件(app-json、apps、builder、buildpacks、builds、cron、docker-options、logs、network、ports、proxy、ps、registry、resource、scheduler、scheduler-k3s、storage)的
:report --format json输出不再带<plugin>-前缀段,与 Bash 插件输出形状一致,但旧键在 0.38.x 补丁系列中仍会并存输出以保持兼容。
对外部运维脚本而言,这意味着读取 ps:report --format json 时应改用 stop-timeout-seconds / global-stop-timeout-seconds / computed-stop-timeout-seconds 这样的新键名。
五、面向用户的实践价值:如何阅读与使用 HISTORY.md
5.1 用 HISTORY.md 定位升级风险
由于 0.38.0 等大版本附带 docs/appendices/0.38.0-migration-guide.md,升级前建议按以下顺序评估:
- 在 HISTORY.md 中定位目标版本小节,确认是否包含
Security与Backwards Compatibility Breaks章节; - 若有
Deprecations/Removals,检查自己是否使用了对应命令(如storage:ensure-directory、旧冒号形式storage:mount); - 对照
Dependencies章节确认 herokuish、pack、procfile-util、dokku-event-listener 等核心依赖的升级情况——这些依赖由 debian/control 第 7 行的Recommends字段声明,直接影响 buildpack 构建与事件处理行为; - 若目标版本存在迁移指南(如 0.38.0),逐条核对其中列举的行为变化,例如
:report键名变化、ENV 文件路径迁移、默认 catch-all 站点等。
5.2 按版本回溯特性能力
HISTORY.md 也是排查"某功能从哪个版本开始可用"的第一手资料。例如:
- 想要 k3s 上的 Helm chart 预览能力,需 ≥ 0.38.17(#8729);
- 想要
apps:list --format json输出,需 ≥ 0.38.21(#8795); - 想要
plugin:list --format json输出,需 ≥ 0.38.22(#8801); - 想要存储挂载支持
--volume-options,需 ≥ 0.38.12(#8711); - 想要 per-app 的 letsencrypt 邮箱配置,需 ≥ 0.38.25(#8849)。
5.3 各版本通用的安装/升级命令
HISTORY.md 中每个版本小节都给出了相同的安装模板,以 0.38.27 为例:
wget -NP . https://dokku.com/install/v0.38.27/bootstrap.sh
sudo DOKKU_TAG=v0.38.27 bash bootstrap.sh
其中 DOKKU_TAG 环境变量用于指定目标版本 tag,-NP 让 wget 覆盖已存在的同名文件。这也是官方推荐的跨版本升级路径:先在测试环境验证迁移指南中的行为变化,再在生产环境执行上述命令。
六、从 0.1.0 到 0.38.27:关键演进脉络
虽然 HISTORY.md 主体是逐版本的变更列表,但其纵向脉络清晰地勾勒出 Dokku 的架构演进(下述路径均为仓库内对应实现,可供进一步阅读):
| 阶段 | 代表版本 | 演进要点 |
|---|---|---|
| 起步期 | 0.1.0(2013-06-15) | 引导脚本 + git 推送 + Nginx 主机名 + Java/Ruby/Node buildpack |
| 插件化 | 0.3.x-0.5.x | git 处理、nginx vhosts、构建流程陆续拆分为插件(见 HISTORY.md 0.1.0 条目下方的演进列表与 plugins/00_dokku-standard) |
| 事件与可观测 | 0.12-0.20 | events 插件(plugins/20_events)、trace、日志体系成型 |
| 多代理支持 | 0.20-0.30 | nginx 之外引入 caddy(plugins/caddy-vhosts)、haproxy(plugins/haproxy-vhosts)、openresty(plugins/openresty-vhosts)、traefik(plugins/traefik-vhosts) |
| 多构建器 | 0.26-0.36 | herokuish 之外引入 nixpacks(plugins/builder-nixpacks)、pack(plugins/builder-pack)、railpack(plugins/builder-railpack)、lambda(plugins/builder-lambda) |
| 多调度器 | 0.30-0.38 | docker-local(plugins/scheduler-docker-local)之外引入 k3s(plugins/scheduler-k3s)与 null(plugins/scheduler-null) |
| Go 化与规范化 | 0.38.x | 大量 Bash 插件迁移为 Go(#3697、#8514、#8804 等),:report 输出统一为 raw/computed/global 三态 |
这种"插件即代码"的结构在 plugins/00_dokku-standard/plugin.toml 中可见一斑:每个插件拥有独立的 plugin.toml 元数据与触发脚本,contrib/release-dokku 在发布时也会统一更新所有插件目录下的版本号。
七、结语
HISTORY.md 不只是一份按时间倒序排列的变更日志,更是理解 Dokku 架构演进、发布工程与升级风险的权威索引。配合 contrib/release-dokku 的自动生成逻辑、docs/development/release-process.md 的 semver 策略、docs/appendices/0.38.0-migration-guide.md 的行为变化说明,以及 debian/control 声明的运行时依赖,读者可以:
- 快速定位任意特性的引入版本与对应 PR;
- 评估升级到新版本时的破坏性风险与迁移动作;
- 理解
:report输出、存储插件、k3s 调度器等模块在 0.38.x 系列中的持续演进方向。
对于正在使用或计划部署 Dokku 的开发者,建议在每次升级前以本文第四节(5.1)给出的检查清单为参照,逐条核对 HISTORY.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 StartedRust0632
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