Dokku 0.38.0 迁移指南:nginx 占位配置、report 重构与配置迁移实战
本文基于 Dokku 仓库中的 0.38.0 迁移指南,系统梳理 0.38 系列版本引入的破坏性变更与行为变化:包括未部署应用的 nginx 502 占位配置、catch-all 默认站点与 TLS 握手行为、:report 输出结构重构(global/computed 键约定)、ENV 文件与弃用环境变量迁移、docker-local 调度器的优雅关闭时序,以及 0.38.25~0.38.27 补丁版本的若干安全与一致性修复。阅读本文后,你将能够判断升级到 0.38.x 时哪些自定义模板、脚本和运维流程需要调整,并能依据源码确认各项新行为的确切实现位置。
一、升级前必读:本指南覆盖的变更范围
0.38.0 是一次涉及面较广的版本,变更点集中在四个方向:
- nginx 代理行为:未部署/无
web进程的应用生成 502 占位配置;新增 catch-all 默认站点并改变 TLS 握手回退行为。 - 配置存储模型:
ENV文件路径迁移、DOKKU_*环境变量迁移为插件属性(plugin properties)。 - report 输出重构:所有
:report子命令支持--global,并引入<plugin>-global-<property>/<plugin>-computed-<property>键约定,Go 插件 JSON 键名去掉插件前缀。 - 调度器与安全修复:docker-local 立即发送
SIGTERM;docker options 与dokku run参数不再经 shell 求值(消除命令注入);storage 插件引入命名卷。
后文按主题逐一展开,每节同时给出官方文档与仓库源码(如 nginx.conf.sigil、scheduler-deploy)作为依据。
二、nginx 对未部署应用的 502 占位配置
2.1 变更内容
0.38.0 起,对于以下三类应用,Dokku 会生成一个最小化的 nginx 配置并返回 502 Bad Gateway:
- 已创建但尚未部署的应用;
- 没有
web进程类型的应用; web进程已停止的应用。
该占位配置的收益(详见 nginx 文档 的 "Nginx Configuration for Undeployed Apps" 一节)包括:
- 域名可解析且返回非 200 状态码:监控工具能够探测到应用异常;
- 支持证书签发工具:如 letsencrypt 需要 nginx 在域名上监听才能完成验证;
- 保留
nginx.conf.d/包含目录:插件可继续注入自定义配置。
502 错误页面内置了自动刷新的 JavaScript,应用可用后页面会自动重新加载。一旦应用部署成功且存在运行的 web 进程,占位配置会被完整的代理配置自动替换。
2.2 源码级印证
该逻辑直接体现在默认模板 plugins/nginx-vhosts/templates/nginx.conf.sigil 中:location / 块根据模板变量 DOKKU_APP_WEB_LISTENERS 是否为空决定行为——
location / {
{{ if $.DOKKU_APP_WEB_LISTENERS }}
gzip on;
# ... 各项 proxy_set_header / proxy_timeout 配置
proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
{{ else }}
return 502;
{{ end }}
}
模板变量由 plugins/nginx-vhosts/functions 注入:有监听器时设为 127.0.0.1:5000 之类的值,无监听器时设为空字符串。单元测试 plugins/nginx-vhosts/template_test.go 中的 TestTemplate_NoWebListenersReturns502 明确断言:当 DOKKU_APP_WEB_LISTENERS 为空时,渲染结果包含 return 502; 且不包含 proxy_pass。502 错误页模板位于 plugins/nginx-vhosts/templates/502-error.html。
2.3 对自定义 sigil 模板的影响
如果你使用自定义的 nginx.conf.sigil 模板并引用了 DOKKU_APP_WEB_LISTENERS,请注意:在为无运行 web 进程的应用渲染模板时,该变量可能为空。自定义模板必须优雅处理这种情况,例如用条件判断改为返回错误页而非代理:
location / {
{{ if $.DOKKU_APP_WEB_LISTENERS }}
proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
{{ else }}
return 502;
{{ end }}
}
同时注意,模板中对 DOKKU_APP_LISTENERS 的使用已被废弃,应改用 DOKKU_APP_WEB_LISTENERS(functions 会输出弃用告警)。
三、catch-all 默认站点与 TLS 握手行为变化
3.1 上游 nginx 默认 vhost 的处置
在全新 apt 安装时,为避免与 Dokku 生成的默认站点冲突导致 duplicate default server for 0.0.0.0:80 错误,以下文件会被重命名为 ${path}.dokku-disabled(重命名而非删除):
/etc/nginx/sites-enabled/default/etc/nginx/sites-available/default/etc/nginx/conf.d/default.conf
如果你对上游默认 vhost 做过本地定制,可通过检查 .dokku-disabled 同名兄弟文件找回。就地升级(upgrade-in-place)安装不会改动任何现有 nginx 文件。
3.2 新增的 catch-all 默认站点
全新 apt 安装现在会附带 /etc/nginx/conf.d/00-default-vhost.conf,用于拒绝 Host 头(或 TLS SNI)不匹配任何已部署应用的请求。其内容(见源码模板 plugins/nginx-vhosts/templates/default-site.conf)为:
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
access_log off;
ssl_reject_handshake on;
return 444;
}
- HTTPS 请求通过
ssl_reject_handshake on直接拒绝握手; - HTTP 请求通过
return 444直接关闭连接、不返回任何响应。
00- 前缀保证该文件先于 /etc/nginx/conf.d/dokku.conf 被加载,从而在逐应用 server 块加载前就确立各端口的 default_server。
3.3 nginx < 1.19.4 的 HTTP-only 变体
ssl_reject_handshake 指令在 nginx 1.19.4 才引入。对于 Debian Bullseye(自带 nginx 1.18.0)等旧版本系统,postinst 会安装仅含 HTTP 监听的变体(源码模板 default-site-legacy.conf):
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log off;
return 444;
}
在这些系统上,对未知主机的 HTTPS 握手仍会回退到按字典序排第一的 443 server 块并展示其证书(与 0.38.0 之前行为一致)。
3.4 TLS 握手行为变化及其影响
行为变化只适用于 nginx 1.19.4+ 且安装了含 SSL 监听器的 catch-all 的系统。变化的核心场景是:HTTPS 请求的 hostname 匹配某个已配置的 Dokku 应用,但该应用没有配置 TLS 证书。
| 请求场景 | 0.38.0 之前 | 0.38.0 之后(nginx 1.19.4+) |
|---|---|---|
| HTTPS 到已配置应用的主机名,且应用已有证书 | 正常握手,使用应用证书 | 不变:nginx 通过 SNI 在 TLS 完成前即选中正确 server 块,catch-all 不会被咨询 |
| HTTPS 到已配置应用的主机名,但应用无证书 | 回退到字典序第一的 443 server 块,展示其证书(产生证书不匹配错误) | 握手被 catch-all 拒绝(ssl_reject_handshake on) |
| HTTPS 到服务器 IP、无 SNI 或 SNI 不匹配任何应用 | 回退到第一个 443 server 块 | 握手被拒绝 |
这对多数场景是正确性改进(不再向客户端展示错误证书),但如果你刻意依赖旧的回退证书行为(例如用于监控探测),需要为对应应用配置证书,或在该主机上移除 catch-all。
3.5 catch-all 的安装期与安装后管理
- 安装期禁用:在
dokku/install_default_sitedebconf 提示中选择 "No",或预置答案:echo 'dokku dokku/install_default_site boolean false' | debconf-set-selections - 安装后自定义:编辑
/etc/nginx/conf.d/00-default-vhost.conf后执行dokku nginx:reload。例如把return 444;改为return 410;以返回 410 Gone。 - 安装后禁用(不卸载 Dokku):
mv /etc/nginx/conf.d/00-default-vhost.conf{,.disabled} dokku nginx:reload - 升级/非 apt 安装手动补齐:升级安装不会自动安装 catch-all;可复制随附模板并重载:
cp /var/lib/dokku/core-plugins/available/nginx-vhosts/templates/default-site.conf /etc/nginx/conf.d/00-default-vhost.conf dokku nginx:reload
此外,nginx:reload 本身也是 0.38.0 新增命令(见 nginx.md),会先校验配置合法性,校验通过才发送 reload 信号;配置非法时以非零码退出并打印校验错误。
四、ENV 文件路径迁移与迁移回滚风险(0.38.26/0.38.27 修订)
4.1 路径移动
磁盘上全局 ENV 文件与各应用 ENV 文件的路径都已移动。官方建议:不要直接 source ENV 文件,而应通过插件触发器(plugin triggers)引用环境变量。已有的 ENV 文件会被合并到新位置,并在"排空"后被移除。
后续补丁版本对移除时机做了两处修订:
- 0.38.26 修订:此前应用 ENV 文件要等下次 Dokku 安装才被移除,全局 ENV 文件则从不移除;0.38.26 起两者都在迁移记录后立即处理。
- 0.38.27 修订:若旧路径的 ENV 文件在迁移已记录之后再次出现,它不会再被合并(因为新位置已包含此后的所有变更)。该文件会按以下规则处理:
- 若其值与当前 config 一致 → 直接删除;
- 否则被移到一旁成为
ENV.migrated,并在警告中列出存在分歧的键,供你手动通过dokku config:set重新应用。
这个保留副本仅供人工复核,复核后应删除:Dokku 不再读取它,且它包含了所有未获准导入的内容——包括被故意 unset 的键,对已吊销的密钥而言,这意味着磁盘上残留着一份敏感信息副本。
4.2 0.38.26 的 ENV 回滚问题与人工修复方法
0.38.26 升级会把残留的 pre-0.38.0 ENV 文件当作"手工编辑"重新合并回当前配置,导致 0.38.0~0.38.25 期间执行过的 dokku config:set / dokku config:unset 被覆盖——包括重新恢复被故意 unset 的变量和密钥。由于运行中的容器保留着创建时的环境,表面上一切正常,但这些"回退"值会在下次部署时进入新容器。
0.38.26 的运行已消费掉残留文件,因此该问题不会二次发生,但也无法自动撤销。检测方法:对从 0.38.26 升级且容器仍在运行的应用,逐一对比 dokku config:show <app> 与 docker exec <container> printenv <key> 的每个键——GIT_REV 在部署后理应不同,其余任何不一致的键即为被回退的值。
修复方法:
# 对发生回退的取值使用 --no-restart 重新设置
dokku config:set --no-restart <app> KEY=VALUE
# 对"复活"的变量使用 --no-restart 再次 unset
dokku config:unset --no-restart <app> KEY
4.3 0.38.26 的插件安装顺序修复
另有 0.38.26 修复:install 步骤在 config 插件之前的那些插件(按字母序安装的 apps、builder、checks)所读取的弃用 DOKKU_* 变量,在升级运行时未能迁移到插件属性——因为它们在 config 插件尚未搬迁 ENV 文件时就读到了旧环境,读到空值且不报告。典型后果是 DOKKU_CHECKS_SKIPPED 丢失,某进程类型"悄悄"恢复了本应跳过的健康检查。修复后,搬迁在任何弃用变量被读取前完成,不受安装顺序影响;受影响安装会在下次 dokku plugin:install --core(升级已自动执行)时恢复,也可用下文第五节的替换命令手动重新设置。
五、DOKKU_* 环境变量迁移为插件属性
一批 DOKKU_* 配置环境变量已被替换为命名空间化的插件属性。升级后首次运行 dokku 时,既有值会自动迁移,原配置变量被 unset,无需手动操作。迁移完成后,通过 dokku config:set 设置这些废弃变量将不再生效,应改用下列属性命令:
| 废弃环境变量 | 替换命令 |
|---|---|
DOKKU_APP_PROXY_TYPE |
dokku proxy:set <app> type <value> |
DOKKU_APP_RESTORE |
dokku ps:set <app> restore <true|false> |
DOKKU_APP_SHELL |
dokku scheduler:set <app> shell <value> |
DOKKU_CHECKS_DISABLED |
dokku checks:disable <app> [proctypes] |
DOKKU_CHECKS_ENABLED |
dokku checks:enable <app> [proctypes] |
DOKKU_CHECKS_SKIPPED |
dokku checks:skip <app> [proctypes] |
DOKKU_CHECKS_WAIT |
dokku checks:set <app> wait <value> |
DOKKU_CHECKS_TIMEOUT |
dokku checks:set <app> timeout <value> |
DOKKU_CHECKS_ATTEMPTS |
dokku checks:set <app> attempts <value> |
DOKKU_DEFAULT_CHECKS_WAIT |
dokku checks:set --global default-wait <value> |
DOKKU_DISABLE_APP_AUTOCREATION |
dokku apps:set --global disable-autocreation <true|false> |
DOKKU_DISABLE_PROXY |
dokku proxy:disable <app> / dokku proxy:enable <app> |
DOKKU_DOCKERFILE_START_CMD |
dokku ps:set <app> dockerfile-start-cmd <value> |
DOKKU_PROXY_PORT |
dokku proxy:set <app> proxy-port <value> |
DOKKU_PROXY_SSL_PORT |
dokku proxy:set <app> proxy-ssl-port <value> |
DOKKU_SKIP_ALL_CHECKS |
dokku checks:disable <app> |
DOKKU_SKIP_CLEANUP |
dokku builder:set <app> skip-cleanup <true|false> |
DOKKU_SKIP_DEFAULT_CHECKS |
dokku checks:skip <app> |
DOKKU_SKIP_DEPLOY |
dokku ps:set <app> skip-deploy <true|false> |
DOKKU_START_CMD |
dokku ps:set <app> start-cmd <value> |
两个特殊说明:
DOKKU_PARALLEL_ARGUMENTS被彻底移除,无替代;DOKKU_SKIP_CLEANUP在/etc/environment或~dokku/.dokkurc/*中设置时仍被尊重(保证 bootstrap 期配置可用),但builder skip-cleanup属性是规范接口,两者同时设置时属性优先。
六、:report 输出结构重构
6.1 --global 标志
所有 :report 子命令现在都接受 --global 标志,将报告范围限定为全局配置属性。它与 --format json 可以组合使用:
dokku scheduler:report --global --format json
此前 --global 与 --format json 组合会报 "info flag" 错误,单独使用 --global 也会被当作未知标志。
6.2 global- / computed- 键约定
每个形如 <plugin>-global-<property> 的 report 键,现在返回原始存储值(属性从未设置时为空),而不再返回替换了内置默认值后的解析值。相应地,新增了 <plugin>-computed-<property> 键:只要该属性存在默认值,就会返回生效值(优先取应用级值,其次全局值,最后内置默认值)。
此变化影响的插件包括:app-json、builder-dockerfile、builder-herokuish、builder-lambda、builder-nixpacks、builder-pack、builder-railpack、caddy、checks、git、haproxy、logs、network、nginx、openresty、proxy、registry、scheduler、scheduler-k3s 和 traefik。
外部工具迁移指引:凡此前读取 <plugin>-global-<property> 并依赖其默认值的脚本,都应改用 <plugin>-computed-<property>。此外,caddy/haproxy/traefik/openresty 中仅全局存在的属性(如 caddy-image、haproxy-log-level、traefik-api-enabled、openresty-image、openresty-letsencrypt-email、openresty-letsencrypt-server、openresty-allowed-letsencrypt-domains-func-base64 等)原本的裸 <plugin>-<property> 键,也被替换为 global- 与 computed- 键对。
6.3 ps 与 cron 插件的键名重命名
ps 与 cron 插件遵循同样的约定,并伴随键名重命名(不保留别名):
ps:report的stop-timeout-seconds、global-stop-timeout-seconds、computed-stop-timeout-seconds分别重命名为ps-stop-timeout-seconds、ps-global-stop-timeout-seconds、ps-computed-stop-timeout-seconds;对应的--<flag>参数同步改名。cron:report的cron-mailfrom、cron-mailto重命名为cron-global-mailfrom、cron-global-mailto,并新增cron-computed-mailfrom、cron-computed-mailto。- 此外,
ps:report --global与cron:report --global现在也会输出每个"可设置且有默认值的全局属性"的computed-键(如ps-computed-procfile-path、ps-computed-stop-timeout-seconds、cron-computed-maintenance、cron-computed-mailfrom、cron-computed-mailto),与其他插件保持一致形态。
6.4 第二轮 report 补充:剩余可设置属性的暴露
第二批 :report 补充把所有"可设置但此前未报告"的属性纳入同一 raw/global/computed 约定,使外部工具可通过 :report --format json 核对漂移,无需回退到通用 bash 任务:
- ps:新增
--ps-dockerfile-start-cmd/--ps-computed-dockerfile-start-cmd、--ps-start-cmd/--ps-computed-start-cmd,以及--ps-skip-deploy/--ps-global-skip-deploy/--ps-computed-skip-deploy(默认false)。 - builder:新增
--builder-skip-cleanup三元组(默认false)。 - scheduler:新增
--scheduler-shell三元组。 - proxy:新增
--proxy-proxy-port、--proxy-proxy-ssl-port三元组,并以--proxy-disabled/--proxy-computed-disabled暴露原始disabled属性(与既有反转的--proxy-enabled并存)。 - openresty:新增
--openresty-global-log-level/--openresty-computed-log-level(默认ERROR)。 - nginx:新增
--nginx-nginx-service-command三元组。 - scheduler-k3s:新增
--scheduler-k3s-global-token,但默认 stdout 输出中该值被掩码为*******,仅在使用--format json或显式按名查询该 flag 时返回原始值。 - traefik:
dns-provider-<env_var>键以--traefik-global-dns-provider-<env_var>形式报告,遵循同样的掩码与显式查询规则;basic-auth-password属性同理,其--traefik-global-basic-auth-password与--traefik-computed-basic-auth-password键在默认 stdout 输出中均被掩码。
6.5 Go 插件 JSON 键名去掉插件前缀
所有 Go 实现的插件(app-json、apps、builder、buildpacks、builds、cron、docker-options、logs、network、ports、proxy、ps、registry、resource、scheduler、scheduler-k3s、storage)的 :report --format json 输出,现在与 bash 插件一致,不再带 <plugin>- 前缀。例如:
dokku ps:report myapp --format json
现在输出 stop-timeout-seconds、global-stop-timeout-seconds、computed-stop-timeout-seconds 键。CLI flag 名称(--ps-stop-timeout-seconds 等)与 :set 语义不变。
向后兼容说明:0.38.x 补丁系列期间,旧的 <plugin>-<property> JSON 键会与新键并存输出,两种形状的外部脚本都能继续工作;旧键将在未来主版本中移除,JSON 消费者应尽早迁移到新键形。
七、docker-local 调度器:优雅关闭时序与 retire 修复
7.1 部署成功后立即发送 SIGTERM
docker-local 调度器现在会在部署成功后立即向旧容器发送 SIGTERM,而不再等待 wait-to-retire 秒后再发送信号。这符合 Heroku 的优雅关闭契约(graceful-shutdown contract),让应用在代理流量切换到新容器的瞬间即可开始排空进行中的工作。
从源码 plugins/scheduler-docker-local/scheduler-deploy 可以看到实现细节:core-post-deploy / post-deploy 触发完成后,对每个旧容器执行 docker container kill --signal=SIGTERM。注释明确说明之所以不用 container stop,是因为 kill --signal 立即返回,而 Docker 不会在非 SIGKILL 信号后自行补发 SIGKILL——后续的硬停止仍由后台块负责。
原有的两段时间约束保持不变(详见 zero-downtime-deploys.md 的 "wait-to-retire" 一节,默认值 60 秒):
wait-to-retire:优雅关闭宽限期,之后再次发送SIGTERM;stop-timeout-seconds:宽限期结束后的硬停止(最终SIGKILL)阈值。
例如设置宽限期:
dokku checks:set node-js-app wait-to-retire 30
7.2 不再排队 retire 仍被使用的镜像
docker-local 调度器不再为"同一应用仍有一个运行中容器在使用"的镜像排队退休任务。这修复了 ps:rebuild 针对基于镜像的部署(git:from-image)产生同 SHA 镜像时,dokku-retire cron 定时器每次运行都记录 Image ... has running containers, skipping rm 的问题。旧版本遗留的卡住条目会在下一次 ps:retire 运行时自动清理。
八、安全修复:参数不再经 shell 求值(0.38.25)与 docker options 修复(0.38.26)
8.1 0.38.25:消除命令注入向量
通过 docker options、dokku run 的 -e/--env 标志以及 --ttl-seconds 提供的值,不再由 shell 求值,而是分词(tokenize)后原样(verbatim)传递。这封堵了一个命令注入向量:此前这些值中的 $(...) 或反引号表达式会在构建、部署或 run 期间以 dokku 用户身份在宿主机上执行。
升级后的行为变化:
$(...)、反引号、$VAR、glob 等 shell 元字符在这些值中被按字面处理,不再展开;--ttl-seconds现在必须是纯整数。
附带修复:traefik docker-options 标签(label key 以 traefik. 开头)中带有孤立反斜杠的反引号,会在升级后首次运行 dokku 时被自动修复,使标签在下一次部署时恢复有效。
8.2 0.38.26:docker options 的移除与规范化重写
从 pre-0.38.0 的 DOCKER_OPTIONS_<PHASE> 文件中排空的 docker options 此前是逐字复制的,而非按 docker-options:add 的存储方式重新序列化,导致 docker-options:remove 用规范字符串去比较一个永远无法匹配的值——命令成功退出却什么都没删。现在改为按 shell 单词(shell word)匹配存储选项,因此可以按原始书写形式移除这些条目。
同时,升级后首次运行 dokku 时,存储的选项会被重写为规范形式:
- 未加引号的 shell 元字符值会被加引号;
- 一行携带多个 flag 的条目会拆成"每 flag 一条"。
这还顺带修复了两个衍生问题:ps:report 从这类多 flag 行读取 restart policy 失败,以及 k3s 调度器只翻译多个 --cap-add/--sysctl flag 中的第一个。通过 docker-options:add 添加的选项本来就是规范形式,不会被改动。
九、scheduler-k3s:Helm release 稳定命名
scheduler-k3s 插件现在把 env 配置和 Dokku 生成的镜像拉取 Secret 各自管理为独立的、名称稳定的 Helm release(config-{app} 与 pull-secret-{app}),不再捆绑进应用 Helm chart 并使用带部署时间戳后缀的名字(env-{app}.{ts} / ims-{app}.{ts})。
这修复了两个 bug:
- 应用 chart 的 Helm rollback 不再删除仍被旧 ReplicaSet 引用的 Secret;
- Deployment 的
imagePullSecrets列表不再跨部署累积指向不存在 Secret 的引用。
升级后,应用的下一次部署会把 Deployment 的 envFrom 与 imagePullSecrets 引用切换到稳定名称并清理泄漏条目;现有运行中的 Deployment 无需手动修补。应用重命名现在也会卸载旧名字下的 tls-{app}、config-{app}、pull-secret-{app} release,新名字的 release 在下一次部署或证书同步时重建。
十、storage 插件:命名卷与迁移
storage 插件现在通过 storage:create、storage:mount、storage:set、storage:destroy 将持久卷作为具名、调度器感知的一等资源管理。
- 旧式的
storage:mount <app> <host>:<container>冒号形式在 docker-local 应用上仍可用但已废弃;在 k3s 应用上会被拒绝。 - 现有冒号形式挂载在插件首次运行(install 触发器期间)时自动迁移,以
legacy-<hash>条目出现在storage:list-entries中;迁移幂等,并与$DOKKU_LIB_ROOT/config/storage/.migrated/<app>标志文件绑定,删除该文件可强制在下次 install 时重新扫描。 storage:ensure-directory命令仍可用,但会输出弃用警告——优先使用storage:create <name> [<path>](路径默认仍是$DOKKU_LIB_ROOT/data/storage/<name>)。- 存储条目名称必须是 DNS-1123 label 且不超过 45 个字符,以便原样用作 Helm release 与 Kubernetes 资源名;旧版
ensure-directory校验器接受的下划线和大写字符对新名称不再合法。迁移合成器始终使用小写十六进制哈希,因此既有数据不会被锁定。
十一、升级检查清单
综合上述变更,升级到 0.38.x 时建议按以下清单排查:
- 自定义 nginx sigil 模板:确认对
DOKKU_APP_WEB_LISTENERS为空的情况有兜底(return 502等);不要再依赖DOKKU_APP_LISTENERS。 - report 消费脚本:改用
--format json+--global;global-键现在返回原始值,需要默认值请读取computed-键;Go 插件 JSON 键已去掉<plugin>-前缀(0.38.x 内新旧键并存)。 - TLS 依赖:如果依赖"无证书应用回退展示其他证书"的行为,需要为应用配置证书或移除 catch-all。
- ENV 文件:确认旧的
ENV.migrated副本已人工复核并删除;对 0.38.26 升级过的应用,用config:show与docker exec ... printenv对比排查被回退的键。 - docker options / run 参数:确认没有依赖 shell 展开的值;
--ttl-seconds使用纯整数;需要移除的旧选项用原始书写形式。 - storage:检查
storage:list-entries中的legacy-*条目,新卷名遵循 DNS-1123 规范。 DOKKU_*变量:迁移表中列出的变量在升级后会自动迁移,后续配置一律改用属性命令,设置废弃变量不再生效。
以上各项的官方叙述均可在 0.38.0 迁移指南、nginx 代理文档 与 零停机部署文档 中交叉验证,源码实现与测试则分别位于 nginx-vhosts 插件、template_test.go 与 scheduler-docker-local 插件 中。
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