Hello fellow rustaceans!
The TLDR is that there's no way to prefetch dependencies with Cargo, so within Docker images dependencies have to be fetched and built whenever the project source changes.
I've run into an inefficiency with cargo lately when building rust packages within Docker images. The naive process is to start with the official rust docker image with all the tooling, add all of the source code with something like COPY . .
, and then use RUN cargo install --path .
or something similar. Now whenever I change my project source, the COPY ...
step is invalidated and every step after it, so on the subsequent build all of the dependencies have to be fetched and compiled again, even if they haven't changed.
In other languages, like JS for example, this is solved by copying over the project file first, installing the dependencies, and then copying over the source. By doing this, changes to the project source don't invalidate the step in which the dependencies are fetched/built, so the build time is dramatically reduced after the first build.
The best solution to this problem that I can foresee is to add a cargo subcommand like cargo prefetch
whose purpose would be to fetch all of the dependencies defined in the Cargo.lock
file and build them for the release target by default, without requiring access to anything in the src
directory. If this subcommand existed, one could copy over all their project config, run cargo prefetch
, and then copy over the rest of their source, and then finally run their build command of choice.
My workaround at the moment is basically just copying over all the project config and a src
directory with a boilerplate main.rs
, running a preliminary release build, then copying over all the actual source and running the build again.
I have considered the solution of just not developing within Docker images and instead only building within a Docker image when the project's mostly done, but it's just not tenable for me. Many of the projects I work on require complex infrastructure which demands the app be tested inside a compose setup, so testing builds inside of Docker images is a must.
If a cargo command already exists for this please let me know. I looked but might have missed it. Otherwise, I think this could be a useful command to add to cargo, and not one that I think would require groundbreaking work.
Please let me know your thoughts on this. I haven't been working with rust for long, only about a year or so, so I'd love to learn about any potential design patterns or policies rust employs that would bar it from such a subcommand. Anyways thanks for reading!