Hi,
I'm currently running my Rust binary via a Dockerfile:
# Build stage
FROM rust:slim as builder
RUN apt-get update && \
apt-get install -y pkg-config make g++ libssl-dev cmake libmariadb-dev-compat && \
rustup target add x86_64-unknown-linux-gnu
WORKDIR /var/www/app
COPY . .
RUN cargo build --release
# Prod stage
FROM gcr.io/distroless/cc
COPY --from=builder /var/www/app/target/release/isumis /
CMD ["./isumis"]
After every change in my code I have to delete the Docker image and rebuild it completly. Is there a solution to run the Container with my changes?
A simple way would be using Docker cache mount, i.e. replacing RUN cargo build --release
with something like RUN --mount=type=cache,target=target cargo build --release
.
A more specialized way is using cargo-chef
1 Like
You can optimize this by splitting your dependency build and updates, but in practice it's a pain to get cargo to actually build dependencies without actually using them in code.
For quicker turnaround, you might want to have a build from a "known good" version of the source first, something like:
# Build stage
FROM rust:slim as builder
RUN apt-get update && \
apt-get install -y pkg-config make g++ libssl-dev cmake libmariadb-dev-compat && \
rustup target add x86_64-unknown-linux-gnu
WORKDIR /var/www/app
# other build files...
COPY Cargo.toml Cargo.lock .
# first build last known good, so we can at least already have the dependencies
COPY src-lkg src
RUN cargo build --release
COPY src src
RUN cargo build --release
And then you can copy over your src to src-lkg when you make major changes you don't want to have to rebuild.
There's a few other steps you can further decrease build times like not using --release
or otherwise enable incremental builds.
Another option is to simply mount your local directory to the rust image using something docker run -v /your/host/project:/your/container/project
, and use docker as essentially just a super-jail for the rust install, but that loses most of the value of being in docker in the first place, and performance of mounts may be an issue (depends on your OS and docker config)
1 Like
When I'm using cargo chef
then my actix web
program stops directly.
# Build stage
FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef
RUN apt-get update && \
apt-get install -y pkg-config make g++ libssl-dev cmake libmariadb-dev-compat && \
rustup target add x86_64-unknown-linux-gnu
WORKDIR /var/www/app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /var/www/app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN cargo build --release
# Prod stage, removing the Rust toolchain
FROM debian:buster-slim AS runtime
WORKDIR /var/www/app
COPY --from=builder /var/www/app/target/release/isumis /usr/local/bin
CMD ["/usr/local/bin/isumis"]
I don't see anything particularly problematic, except maybe that you might have to install ca-certificates
in the prod stage if you use openssl in for actix-web https. You could also try using the gcr.io/distroless/cc
image for the prod stage as you were doing before.
Instead of using cargo chef
I test everything on my local machine and then create a Docker container afterwards. This is way more easier and it is not a waste of time testing everything.