Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache Rust dependencies with Docker build

I have hello world web project in Rust + Actix-web. I have several problems. First is every change in code causes recompiling whole project including downloading and compiling every crate. I'd like to work like in normal development - it means cache compiled crates and only recompile my codebase. Second problem is it doesn't expose my my app. It's unreachable via web browser

Dockerfile:

FROM rust  WORKDIR /var/www/app  COPY . .  EXPOSE 8080  RUN cargo run 

docker-compose.yml:

version: "3" services:   app:     container_name: hello-world     build: .     ports:       - '8080:8080'     volumes:       - .:/var/www/app       - registry:/root/.cargo/registry  volumes:   registry:     driver: local 

main.rs:

extern crate actix_web;  use actix_web::{web, App, HttpServer, Responder};  fn index() -> impl Responder {     "Hello world" }  fn main() -> std::io::Result<()> {     HttpServer::new(|| App::new().service(web::resource("/").to(index)))         .bind("0.0.0.0:8080")?         .run() } 

Cargo.toml:

[package] name = "hello-world" version = "0.1.0" authors = [] edition = "2018"  [dependencies] actix-web = "1.0" 
like image 355
Arek C. Avatar asked Oct 20 '19 13:10

Arek C.


People also ask

Does Docker build cache?

Docker's build-cache is a handy feature. It speeds up Docker builds due to reusing previously created layers. You can use the --no-cache option to disable caching or use a custom Docker build argument to enforce rebuilding from a certain step.

Does Docker pull cache?

Pulling cached images After you configure the Docker daemon to use the Container Registry cache, Docker performs the following steps when you pull a public Docker Hub image with a docker pull command: The Docker daemon checks the Container Registry cache and fetches the images if it exists.

Where does Docker store build cache?

About the Docker Build CacheDocker images are built in layers, where each layer is an instruction from a Dockerfile. Layers stack on top of each other, adding functionality incrementally. The build process knew the Dockerfile didn't change, so it used the cache from the last build for all four layers.

What is Layer Caching in Docker?

Overview. Docker layer caching (DLC) is a great feature to use if building Docker images is a regular part of your CI/CD process. DLC will save image layers created within your jobs, rather than impact the actual container used to run your job.

How to cache dependencies in rust without invalidating the cache?

The gist of it is you need a dummy.rs and your Cargo.toml first, then build it to cache the dependencies and then copy your application source later in order to not invalidate the cache with every build. FROM rust WORKDIR /var/www/app COPY dummy.rs . COPY Cargo.toml .

How to properly cache build folders during a docker build step?

With the (still experimental) Docker Buildkit you can finally properly cache build folders during a docker build step: # syntax=docker/dockerfile:experimental from rust ENV HOME=/home/root WORKDIR $HOME/app [...] RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/home/root/app/target \ cargo build --release

What is this dockerfile frontend syntax implementation for rust?

This is an alternate Dockerfile frontend syntax implementation for Rust: it converts a Cargo.toml (a file listing cargo / Rust dependencies and things) into a docker build able recipe by adding this # syntax line (+ caveats) # syntax = denzp/cargo-wharf-frontend:v0.1.0-alpha.2 [package] ...

What is the best Docker images builder for rust?

Following my first blog post ever on a similar subject I found cargo-wharf, a cacheable and efficient Docker images builder for Rust.


1 Answers

Seems like you are not alone in your endeavor to cache rust dependencies via the docker build process. Here is a great article that helps you along the way: https://blog.mgattozzi.dev/caching-rust-docker-builds/

The gist of it is you need a dummy.rs and your Cargo.toml first, then build it to cache the dependencies and then copy your application source later in order to not invalidate the cache with every build.

Dockerfile

FROM rust WORKDIR /var/www/app COPY dummy.rs . COPY Cargo.toml . RUN sed -i 's#src/main.rs#dummy.rs#' Cargo.toml RUN cargo build --release RUN sed -i 's#dummy.rs#src/main.rs#' Cargo.toml COPY . . RUN cargo build --release CMD ["target/release/app"] 

CMD application name "app" is based on what you have specified in your Cargo.toml for your binary.

dummy.rs

fn main() {} 

Cargo.toml

[package] name = "app" version = "0.1.0" authors = ["..."] [[bin]] name = "app" path = "src/main.rs"  [dependencies] actix-web = "1.0.0" 

src/main.rs

extern crate actix_web;  use actix_web::{web, App, HttpServer, Responder};  fn index() -> impl Responder {     "Hello world" }  fn main() -> std::io::Result<()> {     HttpServer::new(|| App::new().service(web::resource("/").to(index)))         .bind("0.0.0.0:8080")?         .run() } 
like image 164
ckaserer Avatar answered Sep 20 '22 14:09

ckaserer