Dockerfile for small Rust images (with dependency build caching)
Introduction
After reading multiple tutorials for building docker images and optimize them, I compiled an optimized Dockerfile that can:
- Have final images that are small, in the 50MB range
- Benefit from docker caching, allowing to have build times under 10s if you don’t change dependencies
We will assume here you start with a project my_app
you already have or have created with cargo new
.
Setting up
We use this docker file. This technique is called a multi-stage build. When docker builds with docker build
or docker compose build
, it creates two successive images:
- One that serve to create the binary
- One that will execute the binary without the build environment
The second one can be minimized by removing unecessary system components that are already bundled in the produced binary.
## BUILDER IMAGE
+Setting up We use this docker file.">Dockerfile for small Rust images (with dependency build caching) Dockerfile for small Rust images (with dependency build caching)
Introduction
After reading multiple tutorials for building docker images and optimize them, I compiled an optimized Dockerfile that can:
- Have final images that are small, in the 50MB range
- Benefit from docker caching, allowing to have build times under 10s if you don’t change dependencies
We will assume here you start with a project my_app
you already have or have created with cargo new
.
Setting up
We use this docker file. This technique is called a multi-stage build. When docker builds with docker build
or docker compose build
, it creates two successive images:
- One that serve to create the binary
- One that will execute the binary without the build environment
The second one can be minimized by removing unecessary system components that are already bundled in the produced binary.
## BUILDER IMAGE
FROM rust:1.73 as builder
WORKDIR /usr/app
@@ -55,4 +55,4 @@
version = "0.3"
You can learn more about what is jemalloc here
If you use things that are dependent of ssl, such as reqwest, you might also need to tweak the dependency to include rust-tls
:
reqwest = {version = "0.11", default-features = false, features = ["json", "rustls-tls"] }
Running
Try to docker build
your image. If it is successful, try to docker run
the obtained container. It should execute your binary.
You notice your first docker build
was probably long, several minutes long perhaps.
Try to modify your sources, then docker build
again. You should notice the build to be significantly faster.
Use docker images
and inspect image size. Smaller images are faster to push and pull over network, they also cost less to store.
Conclusion
We learned to make a multi-stage build to produce small docker images for Rust, and use the best of docker caching to avoid a costy rebuild
-of dependencies at every source change.
Thanks to / further reading