Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
420 views
in Technique[技术] by (71.8m points)

docker - Compiling a containerized rust application to run on raspberry pi 4 (arm64/armv8). Can't execute "No such file or directory"

I am trying to run a rust application (server) on a raspberry pi (raspberry pi 4) cluster (k3s, docker). I can compile my docker image using buildx successfully and run it on the raspberry pi when targeting the arm64 architecture

ex: docker buildx build --load --platform=linux/arm64 -t myrepo/myapp:arm-0.0.1 .

Setting the dockerfile command to CMD ["echo", "hi i'm working!"], echos "hi i'm working!" as expected. This is nice because I know that buildx is working.

My issue comes when trying to get Rust to work as an executable in the container, the following is my dockerfile

FROM rust as builder
ARG APP_NAME="app"
ARG TARGET="x86_64-unknown-linux-musl"
ARG GITHUB_SSH_KEY=""
RUN apt-get update
RUN apt-get install musl-tools gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf -y
RUN rustup target add $TARGET;
RUN mkdir /usr/src/$APP_NAME
WORKDIR /usr/src/$APP_NAME

ENV CARGO_NET_GIT_FETCH_WITH_CLI=true

COPY Cargo.toml Cargo.lock ./
COPY ./src ./src

RUN mkdir .cargo
RUN if [ "$TARGET" = "armv7-unknown-linux-gnueabihf" ]; then printf '

[target.armv7-unknown-linux-gnueabihf] 
linker = "arm-linux-gnueabihf-gcc"' >> .cargo/config.toml; fi
RUN if [ "$TARGET" = "aarch64-unknown-linux-gnu" ]; then printf '

[target.aarch64-unknown-linux-gnu] 
linker = "aarch64-linux-gnu-gcc"' >> .cargo/config.toml; fi

RUN mkdir /root/.ssh/
RUN echo "$GITHUB_SSH_KEY" > /root/.ssh/id_rsa;
RUN chmod 400 /root/.ssh/id_rsa
RUN ssh-keyscan -H github.com >> /etc/ssh/ssh_known_hosts

RUN cargo build --release --target=$TARGET
RUN groupadd -g 10001 -r $APP_NAME
RUN useradd -r -g $APP_NAME -u 10001 $APP_NAME

# ------------------------------------------------------------------------------
# Final Stage
# ------------------------------------------------------------------------------

FROM scratch
ARG APP_NAME="app"
ARG TARGET="x86_64-unknown-linux-musl"
WORKDIR /user/local/bin/
COPY --from=0 /etc/passwd /etc/passwd
COPY --from=builder /usr/src/$APP_NAME/target/$TARGET/release/$APP_NAME ./app
USER $APP_NAME

ENTRYPOINT ["./app"]

As you can see, I can change my target via build args and have tried armv7, aarch64, and even x86_64 out of blind desperation. All of them build without error. During run time x86_64 predictably failed with the typical "exec format error". However, in both armv7 and aarch64 the error is "no such file or directory". I exec'd into the container and could see that the executables were there, however, I cannot run them. When I inspected the file in the armv7 container I got the following output

ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=211fd9297da768ce435048457849b0ae6b22199a, with debug_info, not stripped

Hoping someone can tell me where I'm going wrong because so far I can't get the app to run containerized on my pi cluster. I'm not finding much helpful documentation out there on how to achieve what I am attempting so I thought I'd try asking here. Any help or insight would be greatly appreciated!

One thing to note is that it all compiles and runs fine without the cross-compilation bit so I am certain the app itself is working.

Also at this point for testing, I'm just trying to run a simple "hello, world!" app.

question from:https://stackoverflow.com/questions/65864484/compiling-a-containerized-rust-application-to-run-on-raspberry-pi-4-arm64-armv8

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your only using musl on x86_64. If you don't use musl and don't disable the standard library then the rust app will depend dynamically on system libc. That library doesn't exist in a scratch docker container. So either use a minimal container that does include a copy of libc like alpine, build a container from scratch that includes libc and its dependencies, or use musl on all architectures.

You should be able to see the libraries needed by running the ldd tool against the executable in the container.

The target strings for musl on arm are: armv7-unknown-linux-musleabihf and aarch64-unknown-linux-musl


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...