Need help with cargo-chef?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

LukeMathWalker
159 Stars 18 Forks 58 Commits 5 Opened issues

Description

A cargo-subcommand to speed up Rust Docker builds using Docker layer caching.

Services available

!
?

Need anything else?

Contributors list

# 128,354
scienti...
rust-la...
diagnos...
gRPC
26 commits
# 252,009
osd
C
sed
cpython
2 commits
# 198,479
Haskell
radeon
opencl
mac
1 commit
# 115,958
Rust
Twitter
actix
actix-w...
1 commit
# 153,087
Rust
c-plus-...
Qt
vulkan
1 commit
# 118,018
HTML
golang
Docker
sso-aut...
1 commit
# 202,081
python3
rust-la...
React
gitlab-...
1 commit
# 157,617
Rust
Python
session...
login-s...
1 commit
# 525,234
React
CSS
HTML
Docker
1 commit
# 108,215
React
Java
nosql-d...
Kotlin
1 commit

cargo-chef

Cache the dependencies of your Rust project and speed up your Docker builds.



Table of Contents

  1. How to install
  2. How to use
  3. Benefits vs Limitations
  4. License

How To Install

You can install

cargo-chef
from crates.io with
cargo install cargo-chef

How to use

:warning: cargo-chef is not meant to be run locally
Its primary use-case is to speed up container builds by running BEFORE the actual source code is copied over. Don't run it on existing codebases to avoid having files being overwritten.

cargo-chef
exposes two commands:
prepare
and
cook
:
cargo chef --help
cargo-chef

USAGE: cargo chef

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
examines your project and builds a recipe that captures the set of information required to build your dependencies.
cargo chef prepare --recipe-path recipe.json

Nothing too mysterious going on here, you can examine the

recipe.json
file: it contains the skeleton of your project (e.g. all the
Cargo.toml
files with their relative path, the
Cargo.lock
file is available) plus a few additional pieces of information.
In particular it makes sure that all libraries and binaries are explicitly declared in their respective
Cargo.toml
files even if they can be found at the canonical default location (
src/main.rs
for a binary,
src/lib.rs
for a library).

The

recipe.json
is the equivalent of the Python
requirements.txt
file - it is the only input required for
cargo chef cook
, the command that will build out our dependencies:
cargo chef cook --recipe-path recipe.json

If you want to build in

--release
mode:
cargo chef cook --release --recipe-path recipe.json

You can leverage it in a Dockerfile:

FROM lukemathwalker/cargo-chef as planner
WORKDIR app
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM lukemathwalker/cargo-chef as cacher WORKDIR app COPY --from=planner /app/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json

FROM rust as builder WORKDIR app COPY . .

Copy over the cached dependencies

COPY --from=cacher /app/target target COPY --from=cacher $CARGO_HOME $CARGO_HOME RUN cargo build --release --bin app

FROM rust as runtime WORKDIR app COPY --from=builder /app/target/release/app /usr/local/bin ENTRYPOINT ["/usr/local/bin/app"]

We are using four stages: the first computes the recipe file, the second caches our dependencies, the third builds the binary and the fourth is our runtime environment.
As long as your dependencies do not change the

recipe.json
file will stay the same, therefore the outcome of
cargo cargo chef cook --release --recipe-path recipe.json
will be cached, massively speeding up your builds (up to 5x measured on some commercial projects).

If you do not want to use the

lukemathwalker/cargo-chef
image, you can simply install the CLI within the Dockerfile:
FROM rust as planner
WORKDIR app
# We only pay the installation cost once, 
# it will be cached from the second build onwards
RUN cargo install cargo-chef 
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM rust as cacher WORKDIR app RUN cargo install cargo-chef COPY --from=planner /app/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json

FROM rust as builder WORKDIR app COPY . .

Copy over the cached dependencies

COPY --from=cacher /app/target target COPY --from=cacher $CARGO_HOME $CARGO_HOME RUN cargo build --release --bin app

FROM rust as runtime WORKDIR app COPY --from=builder /app/target/release/app /usr/local/bin ENTRYPOINT ["/usr/local/bin/app"]

Benefits vs Limitations

cargo-chef
has been tested on a few OpenSource projects and some of commercial projects, but our testing has definitely not exhausted the range of possibilities when it comes to
cargo build
customisations and we are sure that there are a few rough edges that will have to be smoothed out - please file issues on GitHub.

Benefits of
cargo-chef
:

A common alternative is to load a minimal

main.rs
into a container with
Cargo.toml
and
Cargo.lock
to build a Docker layer that consists of only your dependencies (more info here). This is fragile compared to
cargo-chef
which will instead:
  • automatically pick up all crates in a workspace (and new ones as they are added)
  • keep working when files or crates are moved around, which would instead require manual edits to the
    Dockerfile
    using the "manual" approach
  • generate fewer intermediate Docker layers (for workspaces)

Limitations and caveats:

  • cargo cook
    and
    cargo build
    must be executed from the same working directory. If you examine the
    *.d
    files under
    target/debug/deps
    for one of your projects using
    cat
    you will notice that they contain absolute paths referring to the project
    target
    directory. If moved around,
    cargo
    will not leverage them as cached dependencies;
  • cargo build
    will build local dependencies (outside of the current project) from scratch, even if they are unchanged, due to the reliance of its fingerprinting logic on timestamps (see this long issue on
    cargo
    's repository
    );

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.