67 个版本
0.49.0 |
|
---|---|
0.1.67 | 2024年5月22日 |
0.1.66 | 2024年3月10日 |
0.1.62 | 2023年7月26日 |
0.1.9 | 2020年11月29日 |
#55 in Cargo 插件
38,009 每月下载量
57KB
1K SLoC
cargo-chef
cargo-chef
最初是为 Zero to Production In Rust 的部署章节开发的,这是一本关于使用 Rust 编程语言进行后端开发的实战入门书。
目录
如何安装
您可以使用以下方式从 crates.io 安装 cargo-chef
cargo install cargo-chef --locked
如何使用
⚠️ cargo-chef 不应在本地上运行
其主要用途是通过在将实际源代码复制过来之前运行来加快容器构建速度。不要在现有代码库上运行它,以避免文件被覆盖。
cargo-chef
提供了两个命令:prepare
和 cook
cargo chef --help
cargo-chef
USAGE:
cargo chef <SUBCOMMAND>
SUBCOMMANDS:
cook Re-hydrate the minimum project skeleton identified by `cargo chef prepare` and
build it to cache dependencies
prepare Analyze the current project to determine the minimum subset of files (Cargo.lock
and Cargo.toml manifests) required to build it and cache dependencies
prepare
检查您的项目并构建一个 配方,该配方捕获构建依赖项所需的信息集合。
cargo chef prepare --recipe-path recipe.json
这里没有太多神秘的事情,您可以检查 recipe.json
文件:它包含您的项目骨架(例如,所有带有相对路径的 Cargo.toml
文件,Cargo.lock
文件也可用)以及一些附加信息。
特别是,它确保所有库和二进制文件都在各自的 Cargo.toml
文件中明确声明,即使它们可以在规范默认位置(二进制的 src/main.rs
,库的 src/lib.rs
)找到。
recipe.json
文件相当于 Python 的 requirements.txt
文件 —— 它是构建依赖项所需的唯一输入,即 cargo chef cook
命令,这个命令将构建我们的依赖项
cargo chef cook --recipe-path recipe.json
如果您想以 --release
模式构建
cargo chef cook --release --recipe-path recipe.json
您还可以选择覆盖使用哪个 Rust 工具链。例如,强制使用 nightly
工具链
cargo +nightly chef cook --recipe-path recipe.json
cargo-chef
被设计成可以在 Dockerfile 中使用
FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef
WORKDIR /app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Build dependencies - this is the caching Docker layer!
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY . .
RUN cargo build --release --bin app
# We do not need the Rust toolchain to run the binary!
FROM debian:bookworm-slim AS runtime
WORKDIR /app
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]
我们使用三个阶段:第一阶段计算配方文件,第二阶段缓存我们的依赖项并构建二进制文件,第三阶段是我们的运行时环境。
只要您的依赖项没有更改,recipe.json
文件将保持不变,因此 cargo chef cook --release --recipe-path recipe.json
的输出将被缓存,大大加快您的构建速度(在某些商业项目中测得高达 5 倍)。
预构建镜像
我们提供 lukemathwalker/cargo-chef
作为预构建的 Docker 镜像,其中包含 Rust 和 cargo-chef
。
标记方案为 <cargo-chef version>-rust-<rust version>
。
例如,0.1.22-rust-1.56.0
。
您可以通过使用来选择获取 cargo-chef
或 rust
的最新版本
latest-rust-1.56.0
(使用特定 Rust 版本的最新cargo-chef
);0.1.22-rust-latest
(使用特定cargo-chef
版本的最新 Rust)。您可以在 Dockerhub 上的所有可用标签 中找到。
⚠️ 您必须在所有阶段使用相同的 Rust 版本
如果您在一个阶段中使用不同的 Rust 版本,缓存将无法按预期工作。
不使用预构建镜像
如果您不想使用 lukemathwalker/cargo-chef
镜像,您可以在 Dockerfile 中简单安装 CLI
FROM rust:1 AS chef
# We only pay the installation cost once,
# it will be cached from the second build onwards
RUN cargo install cargo-chef
WORKDIR app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Build dependencies - this is the caching Docker layer!
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY . .
RUN cargo build --release --bin app
# We do not need the Rust toolchain to run the binary!
FROM debian:bookworm-slim AS runtime
WORKDIR app
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]
在 Alpine 上运行二进制文件
如果您想使用 alpine
发行版运行应用程序,您需要创建一个完全静态的二进制文件。
推荐的方法是使用 muslrust
构建 x86_64-unknown-linux-musl
目标。
cargo-chef
支持 x86_64-unknown-linux-musl
,但我们正在进行 交叉编译 —— 目标工具链必须明确指定。
一个示例 Dockerfile 看起来像这样
# Using the `rust-musl-builder` as base image, instead of
# the official Rust toolchain
FROM clux/muslrust:stable AS chef
USER root
RUN cargo install cargo-chef
WORKDIR /app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Notice that we are specifying the --target flag!
RUN cargo chef cook --release --target x86_64-unknown-linux-musl --recipe-path recipe.json
COPY . .
RUN cargo build --release --target x86_64-unknown-linux-musl --bin app
FROM alpine AS runtime
RUN addgroup -S myuser && adduser -S myuser -G myuser
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/app /usr/local/bin/
USER myuser
CMD ["/usr/local/bin/app"]
优势与限制
cargo-chef
已在一些开源项目和部分商业项目中进行了测试,但我们的测试显然还没有穷尽关于cargo build
定制化的可能性范围,我们确信还有一些需要平滑处理的地方边缘 - 请在GitHub上提交问题。
cargo-chef
的好处
一个常见的替代方法是加载一个最小化的main.rs
到一个包含Cargo.toml
和Cargo.lock
的容器中,以构建一个只包含您的依赖项的Docker层(更多信息请参见这里)。与cargo-chef
相比,这更加脆弱,因为cargo-chef
将
- 自动获取工作空间中的所有crate(以及随着添加的新crate)
- 在文件或crate移动时继续工作,而手动方法需要手动编辑
Dockerfile
- 生成更少的中间Docker层(对于工作空间)
局限性和注意事项
cargo chef cook
和cargo build
必须从相同的工目录中执行。如果您使用cat
检查您的一个项目下的*.d
文件,您会发现它们包含指向项目target
目录的绝对路径。如果移动,cargo
将不会利用它们作为缓存的依赖项;cargo build
将从零开始构建本地依赖项(当前项目之外的),即使它们未更改,这也归因于其指纹逻辑对时间戳的依赖(请参见在cargo
仓库中的这个问题);
许可协议
根据您选择,受Apache License,Version 2.0或MIT许可协议的许可。除非您明确声明,否则您提交的任何旨在包含在您提交的此crate中的贡献,根据Apache-2.0许可协议定义,应如上所述双重许可,不得附加任何额外条款或条件。
依赖项
~7–17MB
~205K SLoC