PostHog 的 Depot 容器构建实战:depot build / depot bake 用法、缓存机制与 CI 迁移指南

PostHog 的 Depot 容器构建实战:depot build / depot bake 用法、缓存机制与 CI 迁移指南

【免费下载链接】posthog :hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP. 【免费下载链接】posthog 项目地址: https://gitcode.com/GitHub_Trending/po/posthog

PostHog 仓库通过 .agents/skills/depot-container-builds/SKILL.md 沉淀了一套 Depot 远程容器构建技能文档,覆盖 depot builddepot bake 的完整用法、Docker Compose 集成、从 docker build/docker buildx 的迁移方式,以及常见错误的修复对照表。本文以该文档为主体,结合仓库中真实的 depot.json主构建工作流Dockerfile 源码,讲清楚 Depot 远程构建的运行机制、输出模式选择、缓存优化原则,以及 PostHog 团队在实战中踩过的坑(这些坑同时记录在 docs/internal/ci-things-already-tried.md)。读完本文,你可以掌握:如何在 CI 中用 Depot 替代本地 docker build、如何配置多镜像并行 bake、如何避免把镜像构建慢上加慢的常见配置错误。

一、Depot 在 PostHog 中的定位与运行原理

Depot 把 Docker 镜像构建放到远端的高性能构建机上执行——官方规格为 16 CPU、32 GB RAM、带 NVMe SSD 缓存的临时 EC2 实例。depot builddocker build / docker buildx build 的"即插即用"替代,depot bake 则替代 docker buildx bake

PostHog 仓库中这一能力的接入方式可以从三处源码证据得到印证:

  1. 项目标识文件:仓库根目录的 depot.json(以及 rust/depot.json)内容为 {"id": "x19jffd9zf"},即 Depot CLI 用来确定构建归属的项目 ID。

  2. CI 工作流.github/workflows/container-images-cd.yml 中同时使用了 depot/setup-action(安装 CLI)和 depot/build-push-action 两个 Action,关键参数写得很直白:

    uses: depot/build-push-action@5f3b3c2e5a00f0093de47f657aeaefcedff27d18 # v1.17.0
    with:
      context: . # match the CI build's context so master reuses the shared Depot layer cache
      buildx-fallback: false # the fallback is so slow it's better to just fail
      push: true
    

    两条注释值得注意:context: . 是为了让 master 分支复用 CI 已写入的共享 Depot 层缓存(构建上下文必须一致,层缓存才能命中);buildx-fallback: false 表示 Depot 失败时宁愿报错也回退到本地 buildx,因为回退太慢。

  3. 技能文档来源.agents/skills/depot-container-builds/UPSTREAM.md 说明该 SKILL.md 是从 Depot 官方的 depot/skills 仓库 vendored(同步)而来,PostHog 的容器镜像 CI/CD 正是围绕 depot/build-push-actiondepot/setup-action 构建的,并给出了定期重新同步上游的脚本。

Depot 的核心运行概念(来自技能文档的 Key Concepts 部分):

  • 构建在临时 EC2 实例上远程执行,镜像默认只留在远端缓存里,不会自动落到本地
  • 需要落地时用 --load(下载到本地 Docker daemon)、--push(推到镜像仓库)、--save(存入 Depot 的临时 registry);
  • 层缓存基于持久化 NVMe SSD 全自动生效,无需任何手动缓存配置;
  • 多平台构建使用原生 CPU 构建机并行处理 amd64 与 arm64,不做 QEMU 模拟;
  • 同一 Depot 项目下所有团队成员共享同一份层缓存。

二、多组织用户的项目选择(Project Selection)

容器构建命令的目标是"项目"而非"组织"。技能文档特别警告:如果预期的项目不可见,或构建时意外弹出项目选择提示,通常说明当前默认 org 设错了。排查顺序:

depot org show              # 查看当前 org ID
depot org list              # 列出用户所属的所有 org
depot org switch <org-id>   # 可选:切换默认 org

也可以在构建时用 --project <project-id> 显式指定项目(见下文 depot build 模式),绕开默认 org 的歧义——这一点在多服务共享 compose 文件的场景中尤其有用(PostHog 的 depot.json 就固定了项目 ID,CI 中不再依赖环境默认值)。

三、depot build:核心模式与关键参数

3.1 常用构建模式

技能文档给出了 10 种基本模式,覆盖构建、下载、推送、多平台、暂存、Lint、密钥与 SSH 转发:

# 远程构建(镜像留在远端缓存,本地拿不到)
depot build -t repo/image:tag .

# 构建 + 下载到本地 Docker daemon
depot build -t repo/image:tag . --load

# 构建 + 直接推送到镜像仓库(快——不经过本地网络中转)
depot build -t repo/image:tag . --push

# 多平台构建(原生 CPU 并行,无模拟)
depot build --platform linux/amd64,linux/arm64 -t repo/image:tag . --push

# 存入 Depot 临时 registry(默认 7 天保留)
depot build --save .
depot build --save --save-tag my-tag .

# 关闭 provenance 元数据(修复仓库中显示 "unknown/unknown" 平台的问题)
depot build -t repo/image:tag --push --provenance=false .

# 构建前先 Lint Dockerfile
depot build -t repo/image:tag . --lint

# 携带构建密钥
depot build --secret id=mysecret,src=./secret.txt -t repo/image:tag .

# 转发 SSH agent(用于构建期拉私有仓库依赖)
depot build --ssh default -t repo/image:tag .

# 显式指定 Depot 项目
depot build --project <project-id> -t repo/image:tag .

3.2 关键 Flag 全表

Flag说明
--load把镜像下载到本地 Docker daemon
--push推送到镜像仓库
--save存入 Depot 临时 registry
--save-tag为 Depot Registry 指定自定义 tag
--platform目标平台(linux/amd64linux/arm64 或两者)
--build-platform强制指定构建执行架构(默认 dynamic
--projectDepot 项目 ID
--tokenDepot API token
--lint构建前 Lint Dockerfile
--provenance控制 provenance 凭证(设为 false 可修复 unknown/unknown)
--no-cache本次构建禁用缓存
-f / --file指定 Dockerfile 路径
-t / --tag镜像名与 tag
--target只构建特定 stage
--build-arg设置构建期变量
--secret暴露密钥,格式 id=name[,src=path]
--ssh暴露 SSH agent
--output / -o自定义输出,如 type=local,dest=path

注意 --build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 是一个特殊用法:Depot 远程构建的上下文默认不带 .git 目录,如果 Dockerfile 里的构建脚本(如 git describe 生成版本号)依赖它,就必须显式加这个 build-arg(见下文常见错误表)。

四、depot bake:多镜像并行构建

depot bakedocker buildx bake 的替代命令,用于一次并行构建多个镜像:

depot bake                                    # 按默认文件查找顺序执行
depot bake -f docker-bake.hcl                 # 指定 HCL 文件
depot bake -f docker-compose.yml --load       # 构建 compose 服务并加载到本地
depot bake --save --save-tag myrepo/app:v1   # 存入 Depot Registry
depot bake --print                            # 只打印解析后的配置,不实际构建

默认文件查找顺序compose.yamlcompose.ymldocker-compose.ymldocker-compose.yamldocker-bake.jsondocker-bake.override.jsondocker-bake.hcldocker-bake.override.hcl--print 是排错利器:它只输出解析后的 target 列表而不触发构建,可以在 CI 调试阶段确认平台、tag、args 是否符合预期。

4.1 HCL bake 文件示例

技能文档中的完整示例保留了变量、分组、多平台 target 与 target 间共享上下文(contexts = { app = "target:app" } 表示 worker 复用 app 的构建结果作 base):

variable "TAG" {
  default = "latest"
}

group "default" {
  targets = ["app", "worker"]
}

target "app" {
  dockerfile = "Dockerfile"
  platforms  = ["linux/amd64", "linux/arm64"]
  tags       = ["myrepo/app:${TAG}"]
  args = { NODE_VERSION = "20" }
}

target "worker" {
  dockerfile = "Dockerfile.worker"
  tags       = ["myrepo/worker:${TAG}"]
  contexts   = { app = "target:app" }  # Share base between targets
}

变量可以在命令行覆盖:TAG=v2.0 depot bake

4.2 Docker Compose 中的逐服务项目 ID

同一个 compose 文件里的不同服务可以绑定到不同的 Depot 项目,用 x-depot 扩展字段声明:

services:
  api:
    build:
      dockerfile: ./Dockerfile.api
      x-depot:
        project-id: abc123
  web:
    build:
      dockerfile: ./Dockerfile.web
      x-depot:
        project-id: def456

depot bake -f docker-compose.yml 会按服务各自的 x-depot.project-id 路由到对应项目的缓存。

五、Docker Compose 集成的两种方式

技能文档给出"推荐"与"零改动"两条路线,效率差异明确:

# 推荐:并行构建所有服务后统一加载(共享构建会话,效率最高)
depot bake -f docker-compose.yml --load
docker compose up

# 替代:零代码改动(效率较低,每个服务是独立构建)
depot configure-docker
docker compose build

depot configure-docker 会注册一个 Docker CLI 插件,把本地 docker build 静默路由到 Depot——日志中出现 [depot] 前缀即可确认请求确实走了 Depot。这条路适合过渡期,但每个服务独立构建、无法共享 build 会话,不如 bake 一次并行高效。

六、从 Docker 迁移到 Depot

迁移成本极低,基本是单行替换:

# docker build → depot build(flag 相同,一行替换)
depot build -t my-image .

# docker buildx bake → depot bake
depot bake -f docker-bake.hcl

# 零代码改动方案:通过 Docker 插件接管
depot configure-docker
docker build .  # 请求被路由到 Depot(日志中找 [depot] 前缀确认)

迁移时必须删除的参数——Depot 自动处理缓存,保留这些参数反而制造故障:

  • --cache-from type=gha:会触发 "services aren't available" 错误;
  • --cache-to type=gha:同样的问题;
  • 其他任何手工的 BuildKit 缓存配置(GHA cache 是 GitHub Actions 专属的 buildx 缓存通道,在 Depot 远程构建环境中没有对应服务)。

七、常见错误对照表(技能文档原表全量继承)

错误现象修复
使用了 --cache-from type=gha--cache-to type=gha删掉。Depot 在 NVMe SSD 上自动缓存
多平台镜像在仓库里显示 unknown/unknown 平台--provenance=false
depot build 后期望本地就有镜像--load 下载,或 --push 推到仓库
构建上下文里没有 .git 目录--build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
构建挂起或 "failed to mount" 错误在项目设置中重置缓存,或执行 depot cache reset
拉取基础镜像报 "401 Unauthorized"Docker Hub 限流——用 docker login 认证,或改用 public.ecr.aws/docker/library/ 镜像源
"Keep alive ping failed" / OOM在项目设置里调大 builder 规格或启用自动扩缩

八、PostHog 实战教训:缓存挂载不是越多越好

技能文档开头要求"改 CI 之前先查 things already tried"。该文档中 Docker 相关条目恰好为 Depot 用法提供了反向佐证:

  1. BuildKit cache mounts 全量套用被否决(rejected, 2025-10):照 Depot 官方指南给 apt/pip/uv/node/Playwright 全部加了 cache mount 后,温缓存下后端构建从 52.7s 变慢到 57.5s(约 9%),前端从 55.5s 到 62.2s(约 12%)。原因是 cache mount 即使缓存命中也有 5–7 秒开销,而约 95% 的 PR 只改代码不改依赖,"为罕见场景加速、让常见场景变慢"。

  2. 窄化版本保留下来:最终只给个别昂贵步骤保留挂载。这一点可以直接在 Dockerfile 里验证——当前主 Dockerfile 只剩几个精准挂载:

    RUN --mount=type=cache,id=pnpm,target=/tmp/pnpm-store-v24 \ ...   # L59、L147
    RUN --mount=type=cache,id=npm,target=/root/.npm \ ...             # L152
    RUN --mount=type=cache,id=uv-libxmlsec1.2.37-2,target=/root/.cache/uv \ ...  # L198
    

    其中 id=uv-libxmlsec1.2.37-2 是踩坑后的产物:uv 缓存里残留了对旧版 libxmlsec1 编译的 wheel 导致构建失败,后来的修复是把系统库版本写进 cache ID,库版本一变缓存自动失效。结论:只为测量过的高开销步骤加 cache mount,并把缓存产物所编译依赖的系统库版本编入 cache ID

  3. Docker Hub 限流的迷惑性诊断(2026-08):CI 大面积报 toomanyrequests: ... unauthenticated pull rate limit,但 docker login 全程成功。真因是 Docker Hub 订阅过期——过期后 Docker 签发匿名 token 但仍接受登录。技能文档错误表中"401 Unauthorized → 先认证"的修复方向与之呼应,但 PostHog 的教训补充了:如果认证没问题,先查订阅状态再怀疑密钥。

九、Builder 规格与计费

规格CPU内存每分钟价格适用计划
Default1632 GB$0.004所有计划
Large3264 GB$0.008Startup 及以上
Extra Large64128 GB$0.016Startup 及以上

按秒计费;depot bake 无论包含多少 target 都只按一次构建计费——这对多服务/多镜像仓库是一笔可观的节省。

十、Depot Registry:临时镜像暂存与二次分发

Depot 的临时 registry(默认 7 天保留)适合"先存后取"的 CI 编排——构建一次,多个下游 job 拉取,或直接再推送到正式仓库:

# 存入 Depot Registry
depot build --save -t myapp .

# 拉取已保存的镜像
depot pull --project <id> <build-id>

# 把已保存镜像推送到其他仓库
depot push --project <id> -t registry/image:tag <build-id>

# 用 Docker 直接登录 Depot Registry
docker login registry.depot.dev -u x-token -p <depot-token>
# Registry 地址格式:registry.depot.dev/<project-id>:<tag>

十一、特殊输出格式:estargz 与 zstd

对容器启动速度敏感的部署场景(Fargate、K8s),技能文档给出了两种压缩输出的完整 --output 参数:

# estargz:支持 lazy-pulling,容器启动更快
depot build --output "type=image,name=repo/image:tag,push=true,compression=estargz,oci-mediatypes=true,force-compression=true" .

# zstd 压缩:Fargate/K8s 启动更快
depot build --output type=image,name=repo/image:tag,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true,push=true .

两者的取舍:estargz 的价值在于运行时按需拉取(需要容器运行时支持),zstd 的价值在于压缩率高、解压快(通用性好)。选择哪种取决于运行侧是否支持对应的拉取路径。

十二、小结:Depot 工作流速查

  1. 本地/CI 构建depot build,按需求加 --load / --push / --save;多平台直接 --platform linux/amd64,linux/arm64,原生 CPU 并行、无模拟开销;
  2. 多镜像depot bake(HCL 或 compose 文件),bake 一次计费一次;--print 先行排错;
  3. 零改动过渡depot configure-docker 后沿用 docker build / docker compose build,日志见 [depot] 前缀即生效;
  4. 迁移纪律:删掉 --cache-from/--cache-to type=gha 等手工 GHA 缓存参数;缓存问题用 depot cache reset 而非换回本地 buildx;
  5. 改 CI 前先检索:PostHog 把"已尝试过什么、为什么失败/回滚"沉淀在 docs/internal/ci-things-already-tried.md,其中 Docker 构建条目(cache mount 开销、cache ID 编入系统库版本)是 Depot 调优最直接的参照;
  6. 可追溯性:仓库内 Depot 项目固定于 depot.json,CI 统一经 container-images-cd.ymlbuild-push-action 执行并禁用 buildx 回退,保证 master 与 CI 共享同一份 Depot 层缓存。

【免费下载链接】posthog :hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP. 【免费下载链接】posthog 项目地址: https://gitcode.com/GitHub_Trending/po/posthog

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值