From 5fed178398495564228d1ee715724f48b5fca8a1 Mon Sep 17 00:00:00 2001 From: Denis Cornehl Date: Thu, 18 Dec 2025 06:39:45 +0100 Subject: [PATCH] switch docker build to cargo-chef --- .dockerignore | 1 + dockerfiles/Dockerfile | 72 ++++++++++++++++++------------------------ 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/.dockerignore b/.dockerignore index 1f8c1f086..38ca77416 100644 --- a/.dockerignore +++ b/.dockerignore @@ -16,3 +16,4 @@ /target/ /triagebot.toml archive_cache +.git diff --git a/dockerfiles/Dockerfile b/dockerfiles/Dockerfile index e3b93dd72..5e073580e 100644 --- a/dockerfiles/Dockerfile +++ b/dockerfiles/Dockerfile @@ -1,19 +1,27 @@ # syntax=docker/dockerfile:1 -# To produce a smaller image this Dockerfile contains two separate stages: in -# the first one all the build dependencies are installed and docs.rs is built, -# while in the second one just the runtime dependencies are installed, with the -# binary built in the previous stage copied there. -# -# As of 2019-10-29 this reduces the image from 2.8GB to 500 MB. +FROM rust:1.92-slim-trixie AS chef +# We only pay the installation cost once, +# it will be cached from the second build onwards +RUN cargo install cargo-chef +WORKDIR /build ################# -# Build stage # +# Plan stage # ################# -FROM rust:1.92-slim-trixie AS build +FROM chef AS planner +WORKDIR /build + +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +################# +# Build stage # +################# +FROM chef AS build ENV DEBIAN_FRONTEND=noninteractive # Install packaged dependencies @@ -34,51 +42,33 @@ RUN apt-get update && \ mold \ clang -ENV PATH=/root/.cargo/bin:$PATH +WORKDIR /build -# get the git SHA from the build args, for our generated version numbers -ARG GIT_SHA=dev -ENV GIT_SHA=$GIT_SHA +COPY --from=planner /build/recipe.json recipe.json # Configure linking to use mold instead for speed (need to use clang because gcc # is too old on this image) ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS=-Clink-arg=-fuse-ld=mold -# Build the dependencies in a separate step to avoid rebuilding all of them -# every time the source code changes. This takes advantage of Docker's layer -# caching, and it works by copying the Cargo.{toml,lock} with dummy source code -# and doing a full build with it. -WORKDIR /build -COPY benches benches -COPY Cargo.lock Cargo.toml ./ -COPY crates crates -COPY .sqlx .sqlx/ -RUN mkdir -p src/bin && \ - echo "fn main() {}" > src/bin/cratesfyi.rs && \ - echo "fn main() {}" > build.rs ARG PROFILE=release + +# Build dependencies - this is the caching Docker layer! RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry,sharing=locked \ --mount=type=cache,target=/build/target,id=cargo-target,sharing=locked \ - cargo build --profile=$PROFILE - -# Dependencies are now cached, copy the actual source code and do another full -# build. The touch on all the .rs files is needed, otherwise cargo assumes the -# source code didn't change thanks to mtime weirdness. -RUN rm -rf src build.rs - -COPY build.rs build.rs -RUN touch build.rs -COPY src src/ -RUN find src -name "*.rs" -exec touch {} \; -COPY templates templates/ -COPY vendor vendor/ -COPY static static/ -COPY assets assets/ -COPY .sqlx .sqlx/ -COPY migrations migrations/ + cargo chef cook --profile=$PROFILE --recipe-path /build/recipe.json + +ENV PATH=/root/.cargo/bin:$PATH + +# get the git SHA from the build args, for our generated version numbers +ARG GIT_SHA=dev +ENV GIT_SHA=$GIT_SHA + +ENV SQLX_OFFLINE=true +# Build application +COPY . . ARG PROFILE_DIR=release RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry,sharing=locked \ --mount=type=cache,target=/build/target,id=cargo-target,sharing=locked \