unix 为什么基于Alpine Linux的Docker镜像无法找到在绝对路径上执行的命令?

rjzwgtxy  于 12个月前  发布在  Unix
关注(0)|答案(2)|浏览(190)

我是Docker的新手。我想容器化一个小环境,这样我就可以运行可执行文件,但我被卡住了,因为我甚至不能运行可执行文件。
我的文件夹结构看起来像这样:

example/
|-Dockerfile
|-hello_world

字符串
我的Dockerfile看起来像这样:

# Use Alpine Linux as the base image
FROM alpine:latest

# Set the working directory inside the container
WORKDIR /app

# Copy the executable to the container
COPY hello_world /app/

# Set the permissions for the executable
RUN chmod +x /app/hello_world

# Define the command to run your server when the container starts
ENTRYPOINT ["/app/hello_world"]


然后我跑:
> sudo docker build -t example .
> sudo docker run --name example_container example
这样做的结果是:
exec /app/hello_world: no such file or directory
我已经尝试了尽可能多的变体,试图在Dockerfile中使用CMDRUNENTRYPOINT,但所有的结果都是相同的,图像无法在根目录下的应用程序文件夹中找到hello_world程序。
我真的很困惑,因为我在我的vanilla Ubuntu操作系统上尝试了这个,我在根目录下放了一个测试文件夹,然后在那里放了一个hello_world,它似乎工作得很好,我可以用这个绝对路径从任何地方运行它。
/app/hello_world是一个可执行文件,它是一段Rust编译代码。当我在Ubuntu机器上的shell中运行/app/hello_world时,它工作得很好。
stable-x86_64-unknown-linux-gnu toolchain/rustc 1.71.0
有人能告诉我我做错了什么吗?

ibrsph3r

ibrsph3r1#

您看到“no such file or directory”错误的原因是系统正在查找嵌入在ELF二进制文件的.interp部分中的路径。对于在glibc下编译的二进制文件,它看起来像:

$ objdump -j .interp -s hello

hello:     file format elf64-x86-64

Contents of section .interp:
 400318 2f6c6962 36342f6c 642d6c69 6e75782d  /lib64/ld-linux-
 400328 7838362d 36342e73 6f2e3200           x86-64.so.2.

字符串
在您的Alpine图像中,没有/lib64/ld-linux-x86-64.so.2,这就是导致错误消息的原因。
以一个C二进制文件为例,如果我开始:

#include <stdio.h>

int main() {
    printf("Hello world.\n");
    return 0;
}


并在我的glibc系统上编译它,然后尝试在Alpine下运行它,我们看到:

$ podman run -it --rm -v $PWD:/src  -w /src alpine
/src # ./hello
/bin/sh: ./hello: not found


如果我们让预期的解释器可用,像这样:

$ podman run -it --rm -v $PWD:/src -w /src \
  -v /lib64/ld-linux-x86-64.so.2:/lib64/ld-linux-x86-64.so.2  alpine


我们得到一个新的错误:

/src # ./hello
./hello: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory


如果我们提供必要的共享库:

$ podman run -it --rm -v $PWD:/src -w /src \
  -v /lib64/ld-linux-x86-64.so.2:/lib64/ld-linux-x86-64.so.2 \
  -v /lib64/libc.so.6:/lib64/libc.so.6  alpine


然后命令按预期工作:

/src # ./hello
Hello world.

lb3vh1jj

lb3vh1jj2#

根据我收到的评论,这里有一个答案,任何人都希望这样做与生 rust 和阿尔卑斯山。
如前所述,问题来自于尝试使用默认的x86_64-unknown-linux-gnu来编译Rust二进制文件。相反,使用x86_64-unknown-linux-musl编译,特别是用途:
rustup target add x86_64-unknown-linux-musl
其次是:
cargo build --release --target=x86_64-unknown-linux-musl
然后将这个新的二进制文件添加到项目中,而不是旧的二进制文件,现在Alpine可以很好地运行它了。

相关问题