building efficient docker images for rust

lets build the smallest, most effficient docker image for our rust apps.

toc

  1. create a simple rust app
  2. speed up build with cargo-chef
  3. code
  4. credits

create a simple rust app

create your own rust program or follow this guide for creating and deploying a minimal axum app with loco

speed up build with cargo-chef

cargo-chef is a tool designed for Rust projects that aims to optimize the build process in Docker environments. It helps in reducing build times by caching dependencies more effectively. It works by first analyzing your Rust project to generate a recipe that contains all the dependencies. This recipe is then used to pre-compile these dependencies, creating a reusable Docker layer. Subsequent builds can use this cached layer to skip re-compiling unchanged dependencies, significantly speeding up the build process. This tool is particularly useful in continuous integration (CI) pipelines where build times are critical.

cargo install cargo-chef --locked

our scaffolded dockerfile from our loco app looks like this:

FROM rust:1.74-slim as builder
WORKDIR /usr/src/
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
WORKDIR /usr/app
COPY --from=builder /usr/src/config /usr/app/config
COPY --from=builder /usr/src/target/release/hello_loco-cli /usr/app/hello_loco-cli
ENTRYPOINT ["/usr/app/hello_loco-cli"]

if we build an image based on the above dockerfile we will get an image of 123mb:

Terminal window
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello_loco latest 0d5bc1271eeb 0 minites ago 123MB

lets use cargo-chef in 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"]

tldr

credits