Building a statically linked binary in Alpine Linux

I did this in Docker to ensure a clean environment. Here’s what happens if I build against x86_64-unknown-linux-musl in Alpine Linux:

λ docker run -it --rm --entrypoint ash rust:1.46.0-alpine
/ # export USER=temp
/ # cargo new temp
     Created binary (application) `temp` package
/ # cd temp
/temp # rustup target add x86_64-unknown-linux-musl
info: component 'rust-std' for target 'x86_64-unknown-linux-musl' is up to date
/temp # cargo build --target x86_64-unknown-linux-musl
   Compiling temp v0.1.0 (/temp)
    Finished dev [unoptimized + debuginfo] target(s) in 0.42s
/temp # ldd target/x86_64-unknown-linux-musl/debug/temp
        /lib/ld-musl-x86_64.so.1 (0x7f1e1a2cb000)

Dynamically linked. (I also tried RUSTFLAGS="-C target-feature=+crt-static" cargo build --target x86_64-unknown-linux-musl but the result was the same.) Here’s what the same procedure results in on Debian:

λ docker run -it --rm --entrypoint bash rust:1.46.0-slim
root@806572e3c056:/# export USER=temp
root@806572e3c056:/# cargo new temp
     Created binary (application) `temp` package
root@806572e3c056:/# cd temp
root@806572e3c056:/temp# rustup target add x86_64-unknown-linux-musl
info: downloading component 'rust-std' for 'x86_64-unknown-linux-musl'
info: installing component 'rust-std' for 'x86_64-unknown-linux-musl'
info: Defaulting to 500.0 MiB unpack ram
 15.3 MiB /  15.3 MiB (100 %)   6.8 MiB/s in  2s ETA:  0s
root@806572e3c056:/temp# cargo build --target x86_64-unknown-linux-musl
   Compiling temp v0.1.0 (/temp)
    Finished dev [unoptimized + debuginfo] target(s) in 1.46s
root@806572e3c056:/temp# ldd ./target/x86_64-unknown-linux-musl/debug/temp
        statically linked

How do I build a statically linked binary inside Alpine Linux? Everything I’ve read says the musl target should be enough.

Did you copy the alpine binary to another machine to test if it can be run?

Edit: You could use readelf -d <binary path> | grep NEED to check for dynamic dependencies.

You’re right, readelf shows no dynamic libraries! I don’t have a Linux machine, so I copied the executable into a scratch Docker image… and it does work, this time. I must have done something incorrectly when I tried it earlier. :man_facepalming: Thank you very much for the help.