执行摘要
- 一句话:修复 sgl-router Docker 构建缺少 Cargo.lock 的问题
- 推荐动作:建议精读以了解 Docker 多阶段构建中处理 gitignore 的常见模式。review 中关于 stub 脆弱的评论值得关注,可在后续 PR 中补充警告注释。
功能与动机
全新检出执行 docker build -f docker/sgl-router.Dockerfile . 失败,因为 Cargo.lock 被 gitignore 导致 COPY 步骤找不到文件。该问题阻塞了新的 nightly-experimental-sgl-router-docker CI 工作流(#26273)的首次运行。
实现拆解
- chef 阶段 lockfile 生成:在
docker/sgl-router.Dockerfile 的 chef 阶段,不再从构建上下文复制 Cargo.lock,改为先 stub 最小源码树(src/main.rs 和 src/lib.rs),然后执行 cargo generate-lockfile 生成锁文件,再运行 cargo chef prepare 导出 recipe。
- builder 阶段 lockfile 传播:builder 阶段不再从构建上下文复制
Cargo.lock,改为从 chef 阶段通过 COPY --from=chef /work/Cargo.lock 获取锁文件,确保两个阶段使用相同的依赖解析。
- 移除 final build 的
--locked:由于 cargo chef cook 可能修改 Cargo.lock,最终 cargo build 去掉 --locked 标志,避免因 chef 阶段锁文件变异而导致构建失败。
- 文档注释更新:Dockerfile 顶部新增注释块,解释 lockfile 生成策略及设计原因,降低未来维护成本。
关键文件:
docker/sgl-router.Dockerfile(模块 部署脚本;类别 infra;类型 infrastructure): 唯一的变更文件,实现了完整的 lockfile 生成和传播逻辑,是本次 PR 的核心。
关键符号:未识别
关键源码片段
docker/sgl-router.Dockerfile
唯一的变更文件,实现了完整的 lockfile 生成和传播逻辑,是本次 PR 的核心。
# `Cargo.lock` 被 repo 根 .gitignore 忽略,
# 因此我们在 chef 阶段通过 stub 最小源码树 + cargo generate-lockfile 生成锁文件,
# 然后传播给 builder 阶段,保证两个阶段使用相同的依赖解析,
# 同时不将 5.5k 行的锁文件提交到仓库。
FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS chef
RUN cargo install cargo-chef --locked --version ^0.1
WORKDIR /work
COPY experimental/sgl-router/Cargo.toml ./
COPY experimental/sgl-router/rust-toolchain.toml ./
# 创建最小 stub 源码,使 cargo 能解析 workspace 和生成 lockfile
RUN mkdir -p src && echo "fn main() {}" > src/main.rs \
&& echo "" > src/lib.rs \
&& cargo generate-lockfile \
&& cargo chef prepare --recipe-path recipe.json \
&& rm -rf src
FROM rust:${RUST_VERSION}-${DEBIAN_VERSION} AS builder
RUN cargo install cargo-chef --locked --version ^0.1
WORKDIR /work
COPY --from=chef /work/recipe.json ./recipe.json
# 从 chef 阶段复制 lockfile,而非构建上下文
COPY --from=chef /work/Cargo.lock ./Cargo.lock
COPY experimental/sgl-router/rust-toolchain.toml ./
RUN cargo chef cook --release --recipe-path recipe.json
COPY experimental/sgl-router/Cargo.toml ./
COPY experimental/sgl-router/src ./src
# 不使用 --locked:因为 cargo chef cook 可能修改 lockfile,
# 严格 --locked 检查会误报失败
RUN cargo build --release --bin sgl-router \
&& strip target/release/sgl-router
评论区精华
gemini-code-assist[bot] 在评论中指出手动创建 stub 源码文件的方案较脆弱,建议在 experimental/sgl-router/Cargo.toml 中添加警告注释,提示结构变更时需同步更新 Dockerfile。当前评论状态为未解决,但 PR 已合并。
- 手动创建 stub 源码的脆弱性 (design): PR 作者未回复直接合并,未添加警告注释,讨论未解决。
风险与影响
- 风险:低风险。变更仅影响
docker/sgl-router.Dockerfile,不涉及任何运行时逻辑。潜在风险:
- 如果 Rust 项目结构变化(如新增二进制入口或修改 lib 路径),chef 阶段的 stub 源码可能不再匹配,导致 chef 阶段失败。此风险已被评论提及,但尚未添加警告注释。
- 移除
--locked 后,若依赖解析在不同构建间产生不一致(例如 registry 更新),可能在 builder 阶段引入意外的依赖版本变更。
- 影响:
- CI 工作流:修复了
nightly-experimental-sgl-router-docker 工作流的阻塞问题,使其能够正常构建 Docker 镜像。
- 本地构建:从全新检出可以成功构建
sgl-router Docker 镜像。
- 维护者:需要了解 Dockerfile 中的 lockfile 生成机制,以防未来项目结构变动时 Dockerfile 失效。
- 风险标记:手动 stub 源码与项目结构耦合, 移除 --locked 可能导致依赖版本不一致
关联脉络
- PR #26273 nightly-experimental-sgl-router-docker workflow: 本 PR 修复了该工作流的首次运行失败问题。#26273 新增的 CI 工作流因缺少 Cargo.lock 而阻塞,本 PR 直接解除了阻塞。
参与讨论