I am trying to dockerise a simple server written in Rust using Rocket.
I managed to get a simple image working but found the image size to be massive. When trying to shrink it I have tried two different things, both seems to result in the same issue. docker exec <name> exited with code 126
It seems like the arbdata.exe file is not being copied across properly.
working Dockerfile (big image)
FROM rust
COPY . /app
WORKDIR /app
RUN cargo build --release
CMD ["./target/release/arb_data"]
first attempt at smaller image
FROM rust as builder
WORKDIR /app
COPY ./ /app
RUN cargo build --release
# gcr.io/distroless/cc-debian11
# rust:slim-buster
# FROM gcr.io/distroless/cc
FROM gcr.io/distroless/cc
COPY --from=builder /app/target/release/arb_data .
CMD ["./arb_data"]
second attempt at a smaller image
ARG BINARY_NAME_DEFAULT=arbdata
FROM clux/muslrust:stable as builder
RUN groupadd -g 10001 -r dockergrp && useradd -r -g dockergrp -u 10001 dockeruser
ARG BINARY_NAME_DEFAULT
ENV BINARY_NAME=$BINARY_NAME_DEFAULT
# Build the project with target x86_64-unknown-linux-musl
# Build dummy main with the project's Cargo lock and toml
# This is a docker trick in order to avoid downloading and building
# dependencies when lock and toml not is modified.
COPY Cargo.lock .
COPY Cargo.toml .
RUN mkdir src
&& echo "fn main() {print!("Dummy main");} // dummy file" > src/main.rs
RUN set -x && cargo build --target x86_64-unknown-linux-musl --release
RUN ["/bin/bash", "-c", "set -x && rm target/x86_64-unknown-linux-musl/release/deps/${BINARY_NAME//-/_}*"]
# Now add the rest of the project and build the real main
COPY src ./src
RUN set -x && cargo build --target x86_64-unknown-linux-musl --release
RUN mkdir -p /build-out
RUN set -x && cp target/x86_64-unknown-linux-musl/release/$BINARY_NAME /build-out/
# Create a minimal docker image
FROM scratch
COPY --from=0 /etc/passwd /etc/passwd
USER dockeruser
ARG BINARY_NAME_DEFAULT
ENV BINARY_NAME=$BINARY_NAME_DEFAULT
ENV RUST_LOG="error,$BINARY_NAME=info"
COPY --from=builder /build-out/$BINARY_NAME /
# Start with an execution list (there is no sh in a scratch image)
# No shell => no variable expansion, |, <, >, etc
# Hard coded start command
CMD ["/arbdata"]
here is a link to the github repo with the working api.
2
Answers
Rust docker image on ubuntu, you can’t run executable from ubuntu on alpine. Try:
Alternatively, compile and built on musl, we have alpine rust image https://registry.hub.docker.com/_/rust/ :
You may want to read https://en.wikipedia.org/wiki/Glibc, https://en.wikipedia.org/wiki/Musl, Why can't I run a C program built on alpine on ubuntu?, Why can't I execute binary copied into a container?, https://en.wikipedia.org/wiki/Dynamic_linker, What is the role of libc(glibc) in our linux app? etc.
You could also statically link C runtime, in which case, you can scratch. How to generate statically linked executables? .
When you want to use a docker image without any
libc
available, you’ll need to statically link your application. This can easily be done like this:You can find a full example here: https://github.com/msrd0/docker-element/blob/main/Dockerfile
I recommend you do not use
rust:alpine
image. It contains a broken version of the rust compiler that refuses dynamic linking not just for the final version but during the entire build process, resulting in the inability to use procedural macros (likeserde_derive
).