# PR #26279 完整报告

- 仓库：`sgl-project/sglang`
- 标题：fix(docker): generate Cargo.lock in chef stage for sgl-router build
- 合并时间：2026-05-25 16:54
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/26279

---

# 执行摘要

- 一句话：修复 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）的首次运行。

# 实现拆解

1. **chef 阶段 lockfile 生成**：在 `docker/sgl-router.Dockerfile` 的 chef 阶段，不再从构建上下文复制 `Cargo.lock`，改为先 stub 最小源码树（`src/main.rs` 和 `src/lib.rs`），然后执行 `cargo generate-lockfile` 生成锁文件，再运行 `cargo chef prepare` 导出 recipe。
2. **builder 阶段 lockfile 传播**：builder 阶段不再从构建上下文复制 `Cargo.lock`，改为从 chef 阶段通过 `COPY --from=chef /work/Cargo.lock` 获取锁文件，确保两个阶段使用相同的依赖解析。
3. **移除 final build 的 `--locked`**：由于 `cargo chef cook` 可能修改 `Cargo.lock`，最终 `cargo build` 去掉 `--locked` 标志，避免因 chef 阶段锁文件变异而导致构建失败。
4. **文档注释更新**：Dockerfile 顶部新增注释块，解释 lockfile 生成策略及设计原因，降低未来维护成本。

关键文件：
- `docker/sgl-router.Dockerfile`（模块 部署脚本；类别 infra；类型 infrastructure）: 唯一的变更文件，实现了完整的 lockfile 生成和传播逻辑，是本次 PR 的核心。

关键符号：未识别

## 关键源码片段

### `docker/sgl-router.Dockerfile`

唯一的变更文件，实现了完整的 lockfile 生成和传播逻辑，是本次 PR 的核心。

```dockerfile
# `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 直接解除了阻塞。