Dockerize Rust application ∫ Actix_web API
Introduction
Lately, I initiated a journey to learn Rust and I started building all my small API/Services with it. Last day after finishing an API it was time to deploy it. For it, as usual, Docker is a nice option to go with. So I started looking for a Dockerfile for Rust and I found a lot of them but nothing that grabbed my attention (large images builds, no layers caching, etc). After trying some (and custom) Dockerfile configuration files I found cargo-chef.
A cargo-subcommand to speed up Rust Docker builds using Docker layer caching.
Deploying an Rust API build with Actix_Web
Actix is a rust actor framework, provides a lot of features out of box, such as actor, sync/async actor, actor with stream, actor with timer, sync/async actor with stream, Typed Message, supervision, Arbiter, Context, Service, Request, Response, Middleware, Mailbox, Syn, etc.
After some trial and error, I managed to have my image build faster than while using the example at Docker or some other search results.
The Dockerfile looked like this:
FROM lukemathwalker/cargo-chef:latest 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
FROM debian:bookworm-slim AS runtime
WORKDIR /app
EXPOSE 8000
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]
The application was building correctly but it wasn't working, while inspecting the logs I encountered the following error:
/usr/local/bin/app: error while loading shared libraries:
libssl.so.3: cannot open shared object file: No such file or directory
After a few searches, I found that it requires OpenSSL to be installed. So I added the following line to the Dockerfile:
# ... previous lines
RUN apt-get update && apt install -y openssl
Now everything works... almost! If you're using Nginx for reverse proxying, you'll need to make sure you also includ the ca-certificates and libssl-dev packages. So the final Dockerfile looks like this:
FROM lukemathwalker/cargo-chef:latest 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
RUN apt-get update && apt install -y openssl ca-certificates libssl-dev && rm -rf /var/lib/apt/lists/*
WORKDIR /app
EXPOSE 8000
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]
This will out an image of ~141.36 MB, which is not bad at all.
Do you have any suggestions, questions, or feedback that you would like to share?