Skip to content

Latest commit

 

History

History
99 lines (53 loc) · 5.33 KB

README.md

File metadata and controls

99 lines (53 loc) · 5.33 KB

Rust Docker Cheatsheet

Notes on building and running Rust binaries in Docker.

Programs

Hello World

Image information for the Rust hello world1 program.

Base Size Libc CRT Linkage
debian 124MB glibc dynamic
debian:slim 80.8MB glibc dynamic
distroless:cc 23MB glibc dynamic
alpine 7.47MB musl static
distroless:static 3.63MB glibc static
scratch 1.29MB glibc static
scratch 416KB musl static

Webserver

Base Size Libc CRT Linkage TLS DNS
scratch 4.49MB glibc static rustls TrustDNS

Base Images

Alpine

Alpine provides the smallest OS while keeping just about everything a Rust program will need to function.

The Rust official Docker support Alpine for building Rust programs through the :alpine tag.

It's important to note that Alpine uses musl libc instead of glibc, and as such you may encounter issues with other libraries expecting the glibc implementaiton, and potentially servere performance differences. The Rust std defaults to using the system allocator, in this instance the malloc implementation provided by musl, however it can be replaced with another allocator by using the global_allocator attribute.

Debian

Debian provides a stable base from which to run any Rust program, and is the default used by the Rust official Docker images.

While providing the most stable and predictable environment, Debian also includes many features, programs, and libraries which are unnecessary for most workloads.

Using the debian:slim tag will shave 40MB off, taking it from 120MB to 80MB, though you'll need to reinstall ca-certificates for typical networked applications.

Distroless

Distroless is an initiative to provide containers with only what is needed to run a given application.

There are a number of flavours provided, however cc and static are most relevent for Rust, and are very slim, coming in at 22MB and 3MB respectively.

Scratch

Scratch, while not technically an image, does provide the means to achieve the smallest image sizes.

Because scratch includes nothing, you will need to provide everything your application needs to operate, including libc, ssl libraries, certificates, etc.

TLS

OpenSSL

Rustls

Rustls is a Rust based TLS implementation leveraging ring for cryptography and webpki for TLS certificate validation. It has good support for recent TLS features and intentionally does not provide support for outdated or insecure uses.

Using rustls allows us to avoid a dependency on OpenSSL, which is usually provided by the OS.

Concepts

Libc, glibc, and musl

Rust "the language" has no dependency on libc (or any c runtime), however, the Rust standard library (std) does2 to provide a convenient and stable way to interact with the host system.

Because Rust programs usually want to use the std, and libc is usually provided by the OS, the base image is an important factor for containerised Rust.

While glibc is the "default" libc, musl is also supported.

Care needs to be taken when choosing to use musl as other linked libraries may not be expecting it, it can have surprising performance implications, and it has relatively less development resources.

C runtime linkage

The Rust standard library supports both static and dynamic linking of the C runtime (CRT). Generally it will be dynamically linked, except for targets specifying musl.

Rust Binary Size

If you're looking to reduce the size of your images and you've already optimised the base image, reducing the size of your Rust binary is a good next step.

There are many factors that affect binary size in Rust, I recommend you start with min-sized-rust.


There are also experimental ways to write rust code with the convenience of std without needing libc/C code, such as rustix + mustang or relibc.

Footnotes

  1. Symbol stripping is enabled.

  2. Use of the std can be disabled with the no_std attribute, in which case the core library will still be available.