This project generates docker images to build static musl binaries using the Rust language. It has several pre-build C/C++ libraries to either speedup the compile time of the Rust project or make it possible to build a project at all like Diesel with MySQL.
These container images are based upon Ubuntu 26.04 and use GCC v15.2.0 to build the toolchains and GCC v15.3.0 for the libraries.
Since 2026-06 all images are build using musl v1.2.6 using https://github.com/crosstool-ng/crosstool-ng.
And since 2025-02-15 all images are available for amd64 and arm64 host platforms.
The following libraries are pre-build and marked as STATIC already via ENV variables so that the Rust Crates know there are static libraries available already.
* ZLib (v1.3.2)
* OpenSSL (v3.5.7)
* cURL (v8.20.0)
* sccache (0.16.0)
* PostgreSQL lib (v17.10) + (v18.4), (v16.14) and (v15.18)
* SQLite (v3.53.2)
* MariaDB Connector/C (v3.4.8) (MySQL Compatible)
* libxml2 (v2.15.3)
To see changes done checkout the Changelog
Both stable and nightly builds are available.
The latest nightly's are always postfixed with -nightly, if you want to use a specific date check if the images exists then you can use the -nightly-YYYY-MM-DD tag.
Nightly's are build every morning around 9:30 UTC.
For stable you can just use the tags listed below, or add -stable to it.
If you want to be sure that you are using a specific stable version you can use -X.Y.Z or -stable-X.Y.Z.
Stables builds are automatically triggered if there is a new version available.
[!TIP] 2025-02-15: Created aarch64 (arm64) images as base container!
From this day on you can also build on aarch64 (arm64) architectures like on a Raspberry Pi 4 or 5.
Or even use the GitHub arm64 runners (Which are used to build the containers for this repo too).
This means that you can build x86_64 (amd64) binaries on an aarch64 (arm64) host.
The OCI images are multi-platform containers and all should work the same for both platforms.
The default PostgreSQL lib used is v17.
If you want to use v17 or v15 you need to overwrite an environment variable so that the postgresql crate will look at the right directory.
Adding -e PQ_LIB_DIR="/usr/local/musl/pq17/lib" at the cli or ENV PQ_LIB_DIR="/usr/local/musl/pq17/lib" to your custom build image will trigger the v17 version to be used during the build.
| Cross Target | Container Tag |
|---|---|
| x86_64-unknown-linux-musl | x86_64-musl |
| armv7-unknown-linux-musleabihf | armv7-musleabihf |
| aarch64-unknown-linux-musl | aarch64-musl |
| arm-unknown-linux-musleabi | arm-musleabi |
To make use of these images you can either use them as your main FROM in your Dockerfile or use something like this:
The images are pushed to multiple container registries.
| Container Registry |
|---|
| https://github.com/BlackDex/rust-musl/pkgs/container/rust-musl |
| https://hub.docker.com/r/blackdex/rust-musl |
| https://quay.io/repository/blackdex/rust-musl |
FROM ghcr.io/blackdex/rust-musl:aarch64-musl as build
COPY . /home/rust/src
# If you want to use PostgreSQL v18 add and uncomment the following ENV
# ENV PQ_LIB_DIR="/usr/local/musl/pq18/lib"
RUN cargo build --release
FROM scratch
WORKDIR /
COPY --from=build /home/rust/src/target/aarch64-unknown-linux-musl/release/my-application-name .
CMD ["/my-application-name"]
If you want to use PostgreSQL v18 client library add -e PQ_LIB_DIR="/usr/local/musl/pq18/lib" before the -v "$(pwd)" argument.
# First pull the image:
docker pull ghcr.io/blackdex/rust-musl:aarch64-musl
# Then you could either create an alias
alias rust-musl-builder='docker run --rm -it -v "$(pwd)":/home/rust/src ghcr.io/blackdex/rust-musl:aarch64-musl'
rust-musl-builder cargo build --release
# Or use it directly
docker run --rm -it -v "$(pwd)":/home/rust/src ghcr.io/blackdex/rust-musl:aarch64-musl cargo build --release
You can also use these images as a GitHub Actions container.
A very simple way looks like this to build aarch64 binaries.
name: "Build container"
on:
push:
branches:
- main
jobs:
build_container:
runs-on: ubuntu-latest
container: ghcr.io/blackdex/rust-musl:aarch64-musl-stable
steps:
- uses: actions/checkout@v4
- name: Build
run: |
cargo build --release
You can verify all my images using the gh client.
For example, to verify the aarch64 v1.96.0 image.
gh attestation verify --owner BlackDex oci://ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.96.0
Sometimes musl based binaries are slower than glibc based binaries.
This is mostly because of the Memory Allocator (malloc) which just isn't that fast.
One way to improve the performance is to use a different allocator within your Rust project.
For example, Vaultwarden uses MiMalloc via mimalloc_rust.
Other Memory Allocators exists too, just see which one fits your application the best.
The tests done after building are testing the MiMalloc crate.
During the automatic build workflow the images are first tested on a Rust projects which test all build C/C++ Libraries using Diesel for the database libraries, and openssl, zlib and curl for the other pre-build libraries.
If the test fails, the image will not be pushed to docker hub.
Because of some strange bugs/quirks it sometimes happens that on some platforms it reports missing __atomic* libraries. The strange thing is, these are available, but for some reason ignored by the linker or rustc (If someone knows a good solution here, please share).
Because of this some platforms may need a(n) (extra) RUSTFLAGS which provides the correct location of the c archive .a file.
| Cross Target | RUSTFLAG |
|---|---|
| arm-unknown-linux-musleabi | -Clink-arg=-latomic |
I started this project to make it possible for Vaultwarden to be build statically with all database's supported. SQLite is not really an issue, since that has a bundled option. But PostgreSQL and MariaDB/MySQL do not have a bundled/vendored feature available.
I also wanted to get a better understanding of the whole musl toolchain and Github Actions, which i did.
Some projects i got my inspiration from: * https://github.com/messense/rust-musl-cross * https://github.com/clux/muslrust * https://github.com/emk/rust-musl-builder
Projects used to get this working: * https://github.com/crosstool-ng/crosstool-ng * https://github.com/cross-rs/cross
Other links for projects used in the past: * https://github.com/richfelker/musl-cross-make
$ claude mcp add rust-musl \
-- python -m otcore.mcp_server <graph>