11# syntax=docker/dockerfile:1
22
3- # To produce a smaller image this Dockerfile contains two separate stages: in
4- # the first one all the build dependencies are installed and docs.rs is built,
5- # while in the second one just the runtime dependencies are installed, with the
6- # binary built in the previous stage copied there.
7- #
8- # As of 2019-10-29 this reduces the image from 2.8GB to 500 MB.
3+ FROM rust:1.92-slim-trixie AS chef
94
5+ # We only pay the installation cost once,
6+ # it will be cached from the second build onwards
7+ RUN cargo install cargo-chef
8+ WORKDIR /build
109
1110# ################
12- # Build stage #
11+ # Plan stage #
1312# ################
1413
15- FROM rust:1.92-slim-trixie AS build
14+ FROM chef AS planner
15+ WORKDIR /build
16+
17+ COPY . .
18+ RUN cargo chef prepare --recipe-path recipe.json
19+
20+ # ################
21+ # Build stage #
22+ # ################
1623
24+ FROM chef AS build
1725ENV DEBIAN_FRONTEND=noninteractive
1826
1927# Install packaged dependencies
@@ -34,51 +42,33 @@ RUN apt-get update && \
3442 mold \
3543 clang
3644
37- ENV PATH=/root/.cargo/bin:$PATH
45+ WORKDIR /build
3846
39- # get the git SHA from the build args, for our generated version numbers
40- ARG GIT_SHA=dev
41- ENV GIT_SHA=$GIT_SHA
47+ COPY --from=planner /build/recipe.json recipe.json
4248
4349# Configure linking to use mold instead for speed (need to use clang because gcc
4450# is too old on this image)
4551ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
4652ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS=-Clink-arg=-fuse-ld=mold
4753
48- # Build the dependencies in a separate step to avoid rebuilding all of them
49- # every time the source code changes. This takes advantage of Docker's layer
50- # caching, and it works by copying the Cargo.{toml,lock} with dummy source code
51- # and doing a full build with it.
52- WORKDIR /build
53- COPY benches benches
54- COPY Cargo.lock Cargo.toml ./
55- COPY crates crates
56- COPY .sqlx .sqlx/
57- RUN mkdir -p src/bin && \
58- echo "fn main() {}" > src/bin/cratesfyi.rs && \
59- echo "fn main() {}" > build.rs
6054
6155ARG PROFILE=release
56+
57+ # Build dependencies - this is the caching Docker layer!
6258RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry,sharing=locked \
6359 --mount=type=cache,target=/build/target,id=cargo-target,sharing=locked \
64- cargo build --profile=$PROFILE
65-
66- # Dependencies are now cached, copy the actual source code and do another full
67- # build. The touch on all the .rs files is needed, otherwise cargo assumes the
68- # source code didn't change thanks to mtime weirdness.
69- RUN rm -rf src build.rs
70-
71- COPY build.rs build.rs
72- RUN touch build.rs
73- COPY src src/
74- RUN find src -name "*.rs" -exec touch {} \;
75- COPY templates templates/
76- COPY vendor vendor/
77- COPY static static/
78- COPY assets assets/
79- COPY .sqlx .sqlx/
80- COPY migrations migrations/
60+ cargo chef cook --profile=$PROFILE --recipe-path /build/recipe.json
61+
62+ ENV PATH=/root/.cargo/bin:$PATH
63+
64+ # get the git SHA from the build args, for our generated version numbers
65+ ARG GIT_SHA=dev
66+ ENV GIT_SHA=$GIT_SHA
67+
68+ ENV SQLX_OFFLINE=true
8169
70+ # Build application
71+ COPY . .
8272ARG PROFILE_DIR=release
8373RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry,sharing=locked \
8474 --mount=type=cache,target=/build/target,id=cargo-target,sharing=locked \
0 commit comments