Dokku 仓库管理指南:使用 repo:gc 与 repo:purge-cache 维护应用 Git 仓库与构建缓存
本文基于当前仓库 docs/advanced-usage/repository-management.md 编写。dokku 的 repository 插件面向每个应用在宿主机上维护的 Git 裸仓库,提供两项核心管理能力:对应用仓库执行
git gc --aggressive压缩回收对象,以及清空跨部署持久化的构建缓存目录。阅读本文后,你将掌握这两个命令的适用场景、执行机制、底层实现原理与验证方法,能够对长期部署、频繁迭代的应用做仓库级"瘦身"与缓存重置。
概述:为什么需要仓库管理
dokku 在宿主机(而非应用容器内部)为每个应用维护一份 Git 仓库,应用代码通过 git push 推入其中,随后触发构建与部署流程。随着应用迭代,仓库中会积累大量历史对象与临时数据,构建过程(尤其基于 buildpacks 的构建)还会在两次部署之间保留一份持久的 cache 目录,避免每次部署重复下载依赖。
repository 插件(核心插件之一,见 plugins/repo/plugin.toml)正是为此提供管理命令:
repo:gc <app> # Runs 'git gc --aggressive' against the application's repo
repo:purge-cache <app> # Deletes the contents of the build cache stored in the repository
[!IMPORTANT] 该功能自 dokku 0.6.0 起提供(New as of 0.6.0)。
两个命令的入口定义在 plugins/repo/src/commands/commands.go 的帮助文本中,运行时统一接受 <app> 参数。插件通过 DOKKU_NOT_IMPLEMENTED_EXIT 环境变量(默认 10)处理未实现子命令的退出码,将命令分发交给各自的子命令可执行文件。
Git 垃圾回收:repo:gc
适用场景
repo:gc 对指定应用的仓库执行 git gc --aggressive。该操作在 Dokku 宿主机上执行,而非在应用容器内。当应用仓库对象膨胀、.git 目录占用空间异常增长,或希望整体压缩仓库对象时,可运行:
dokku repo:gc node-js-app
典型输出与原生 git gc 一致:
Counting objects: 396, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (365/365), done.
Writing objects: 100% (396/396), done.
Total 396 (delta 79), reused 315 (delta 0)
--aggressive 模式比默认的 git gc 更激进:它对所有对象进行更彻底的压缩与增量压缩(delta compression)重算,能获得更高的空间回收率,但代价是执行时间更长、CPU 占用更高,适合在对应用无部署压力时执行。
底层实现:应用仓库的定位与安全保护
从源码 plugins/repo/repo.go 可以看清 repo:gc 的执行机制:
- 定位仓库目录:应用仓库根目录由
AppRoot(appName)计算得出,即$DOKKU_ROOT/<appName>(见 plugins/common/common.go)。 - 保护本地分支引用:执行 GC 前,插件会先读取
<appRoot>/refs/heads/下的所有 head 文件内容到内存,并在git gc执行完成后(通过defer)原样写回。这一步是为了防止git gc --aggressive在清理过程中破坏或改写分支引用,保证仓库的引用安全。 - 执行 GC:通过
common.CallExecCommand调用宿主机上的git命令,参数为gc --aggressive,并设置环境变量GIT_DIR=<appRoot>指向应用仓库,同时将 stderr 流式输出到终端。 - 错误处理:若
git gc失败(退出码非 0),命令返回Unable to run git gc错误并携带 stderr 内容。
命令入口 plugins/repo/subcommands.go 中的 CommandGc 会先调用 common.VerifyAppName 校验应用名是否存在,再执行上述 GC 流程;子命令分发逻辑位于 plugins/repo/src/subcommands/subcommands.go。
验证
仓库自带 Bats 测试 tests/unit/repo.bats 覆盖该命令:先部署应用,再运行 dokku repo:gc $TEST_APP 并断言命令成功退出,可作为该命令在真实部署环境下的行为验证。
清空应用构建缓存:repo:purge-cache
适用场景
使用 buildpacks 构建容器时,dokku 会在两次部署之间保留一个持久的 cache 目录,用于缓存依赖下载、编译中间产物等,以加速后续构建。当出现以下情况时,你可能需要手动清空这份缓存:
- 依赖或构建产物损坏,导致部署失败;
- 需要验证"从零构建"是否可行;
- 构建缓存占用过多磁盘空间。
此时运行:
dokku repo:purge-cache node-js-app
该命令会删除应用构建缓存的全部内容。注意:清空后,下一次部署将重新进行完整的依赖下载与构建,耗时可能明显增加。
底层实现:删除缓存 Volume 与构建容器
从源码 plugins/repo/repo.go 可见,repo:purge-cache 的实现包含两个动作:
- 清理残留构建容器:通过
common.DockerFilterContainers按两个 label 过滤容器——com.dokku.app-name=<appName>与com.dokku.image-stage=build——找出处于构建阶段的容器并调用common.DockerRemoveContainers删除。这确保没有正在进行的构建残留干扰缓存清理。 - 删除缓存 Volume:调用宿主机的 Docker 命令
docker volume rm -f cache-<appName>,即缓存实际存储在名为cache-<appName>的 Docker 卷中(而非仓库目录内)。命令通过common.DockerBin()获取 Docker 可执行文件路径,stderr 流式输出。若删除失败,返回Unable to remove cache volume错误;若卷不存在导致 Docker 退出码非 0,则返回封装了退出码的PurgeCacheFailed错误类型(该类型实现了ExitCode()接口,用于向上层传递正确的退出码)。
命令入口 plugins/repo/subcommands.go 中的 CommandPurgeCache 同样先做 VerifyAppName 校验;子命令分发见 plugins/repo/src/subcommands/subcommands.go。
自动触发场景
除手动执行外,repo:purge-cache 的底层 PurgeCache 函数还会在插件触发器中自动调用(见 plugins/repo/src/triggers/triggers.go):
post-stack-set:当应用更换 buildpack stack 后自动清空缓存,避免旧 stack 的缓存污染新 stack 的构建;post-delete:应用被删除时自动清理其缓存卷,防止残留数据占用磁盘。
这意味着即使不手动执行,dokku 也会在关键生命周期节点维护缓存的正确性。
验证
测试 tests/unit/repo.bats 对缓存清理做了端到端验证:部署应用后先断言存在 1 个带有 com.dokku.app-name=<app> label 的 Docker 卷,执行 dokku repo:purge-cache $TEST_APP 后,再断言该卷数量变为 0,精确验证了缓存卷被删除的效果。
参考与深入阅读
- 插件入口与帮助文本:plugins/repo/src/commands/commands.go
- 核心实现(GC 与缓存清理):plugins/repo/repo.go
- 命令封装与应用名校验:plugins/repo/subcommands.go
- 子命令分发:plugins/repo/src/subcommands/subcommands.go
- 生命周期触发器(stack 更换、应用删除):plugins/repo/src/triggers/triggers.go
- 自动化测试:tests/unit/repo.bats
- 相关文档:构建与 buildpacks 说明、Docker 选项管理、插件管理
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