https://github.com/komar007/cargo-lock-fetch
cargo fetch and cargo vendor with just Cargo.lock
https://github.com/komar007/cargo-lock-fetch
cargo cargolock cli crate crates lockfile registry rust rust-crate
Last synced: 8 months ago
JSON representation
cargo fetch and cargo vendor with just Cargo.lock
- Host: GitHub
- URL: https://github.com/komar007/cargo-lock-fetch
- Owner: komar007
- License: apache-2.0
- Created: 2025-07-25T18:29:14.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-08-04T18:58:36.000Z (10 months ago)
- Last Synced: 2025-09-03T11:10:59.906Z (9 months ago)
- Topics: cargo, cargolock, cli, crate, crates, lockfile, registry, rust, rust-crate
- Language: Rust
- Homepage: https://crates.io/crates/cargo-lock-fetch
- Size: 84 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# `cargo-lock-fetch` - cargo fetch and vendor with just Cargo.lock

[](https://crates.io/crates/cargo-lock-fetch/)
[](https://hub.docker.com/r/komar007/cargo-lock-fetch)


This [cargo](https://doc.rust-lang.org/cargo/) plugin fetches and optionally vendors crates based
only on `Cargo.lock`.
It is particularly useful when building rarely changing docker layers containing just project
dependencies without copying/mounting all `Cargo.toml` files of a multi-crate workspace.
- [Installation](#installation)
- [Usage](#usage)
- [SemVer compatibility](#semver-compatibility)
- [Example: primary use case](#example-primary-use-case)
- [How it works](#how-it-works)
## Installation
`cargo-lock-fetch` is mainly intended to be used with containers. Docker users can copy it from the
binary docker distribution:
``` dockerfile
COPY --from=komar007/cargo-lock-fetch \
/cargo-lock-fetch /usr/local/cargo/bin
```
It's also possible to build from source:
``` sh
cargo install cargo-lock-fetch
```
or install a binary release from github:
``` sh
cargo binstall cargo-lock-fetch # requires cargo-binstall
```
> [!IMPORTANT]
> For reproducible builds, avoid omitting version requirements when specifying dependencies. See
> [SemVer compatibility](#semver-compatibility) for semver guarantees. For `cargo`
> `install`/`binstall` use `cargo-lock-fetch@0.x.y`, for docker images, use specific tag:
> `komar007/cargo-lock-fetch:0.x.y`.
## Usage
To fetch dependencies to cargo’s registry cache:
``` sh
cargo lock-fetch --lockfile-path path/to/Cargo.lock
```
To additionally vendor the dependencies (like `cargo vendor`):
``` sh
cargo lock-fetch --lockfile-path path/to/Cargo.lock --vendor vendor_dir/
```
There is no need to run `cargo lock-fetch` from any specific directory.
## SemVer compatibility
This tool follows the [cargo](https://doc.rust-lang.org/cargo/reference/semver.html) /
[semver](https://semver.org/) guidelines with respect to its CLI interface. At the current
`0.x.y` stage, changes of `x` (MINOR) indicate breaking changes. `cargo-lock-fetch` is close to
declaring a public interface which will be indicated by reaching version `1.0.0`. From this moment,
breaking changes to the CLI interface will be indicated by MAJOR version increments.
## Example: primary use case
The following example is the reason this plugin was written.
Assuming the `Dockerfile` is in the root directory of a cargo project, a minimal setup that caches
project dependencies in a docker layer and rebuilds it only on `Cargo.lock` changes would look like
this:
```dockerfile
FROM rust:1.88.0-alpine3.22 AS builder
# Tools layer
RUN apk update \
&& apk add --no-cache musl-dev \
&& cargo install cargo-lock-fetch
WORKDIR /app
# Dependencies layer: fetch all dependencies, but only rebuild layer
# when Cargo.lock changes.
#
# This is for demonstration only - using cargo-lock-fetch starts to
# matter only when multiple Cargo.toml files are used because the
# project consists of many crates. It eliminates the need to specify
# each and every Cargo.toml file to be copied into the build context.
COPY Cargo.lock .
RUN cargo lock-fetch
# Sources layer: the build runs offline here. This layer rebuilds when
# any file changes, but dependencies are cached in the previous layer.
COPY . .
RUN cargo build --frozen --release
FROM scratch
COPY --from=builder /app/target/release/app /app
CMD [ "/app" ]
```
The example can be tested with `docker compose build` in `examples/fetch-deps-to-layer`.
## How it works
In order to use `cargo` to fetch the crates, `cargo-lock-fetch` creates a cargo package and adds the
dependencies found in the input `Cargo.lock` file to its `Cargo.toml,` and then calls `cargo fetch`
and optionally `cargo vendor`.
Because a single `Cargo.toml` file cannot contain multiple versions of the same crate as
dependencies, and this situation is perfectly correct for cargo packages if the versions are pulled
in indirectly by different dependencies, `cargo-lock-fetch` distributes the list of dependencies
between sub-crates using an approach based on greedy vertex coloring, which is optimal for cluster
graphs (there is an edge between 2 dependencies iff they are different versions of the same crate).