无法使用Rust可执行文件运行Docker镜像

时间:2018-03-04 18:19:22

标签: docker rust dockerfile

我正在尝试用我的二进制文件(用Rust编写)创建一个图像,但是我得到了不同的错误。这是我的Dockerfile

FROM scratch
COPY binary /
COPY .env /
COPY cert.pem /etc/ssl/
ENV RUST_BACKTRACE 1
CMD /binary

建筑物完好无损,但是当我尝试运行时,我得到了这个:

$ docker run binary
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown.
ERRO[0000] error waiting for container: context canceled 

而且:

$ docker run binary /binary
standard_init_linux.go:195: exec user process caused "no such file or directory"

我不知道该怎么做。错误消息对我来说很奇怪。根据{{​​3}}它必须有效。

系统信息:最新的Arch Linux和Docker:

Docker version 18.02.0-ce, build fc4de447b5

我使用C ++程序进行了测试,它的工作正常,包括clang和gcc。

它不适用于基于scratchalpinebusyboxbash的图片,但它适用于postgresql,{{1 }和ubuntu图片。确切的问题是Rust和轻量级docker图像有关 - 否则一切正常。

2 个答案:

答案 0 :(得分:10)

正如@Oleg Sklyar指出的那样,问题是Rust二进制文件是动态链接的。

这可能有点令人困惑,因为许多听说过Rust的人也听说过Rust二进制文件是静态链接的,但这是指板条箱中的Rust代码:crate是静态链接的,因为它们目前都是已知的编译这并不是指程序可能链接到的现有C动态库,例如libc和其他必备库。通常,这些库也可以构建为静态链接的工件(请参阅本文末尾)。要检查您的程序或库是否动态链接,您可以使用ldd实用程序:

$ ldd target/release/t
    linux-vdso.so.1 (0x00007ffe43797000)
    libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fa78482d000)
    librt.so.1 => /usr/lib/librt.so.1 (0x00007fa784625000)
    libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fa784407000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fa7841f0000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007fa783e39000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa784ca2000)

您的Docker镜像中需要这些库。你还需要翻译;要获得其路径,您可以使用objdump实用程序:

$ LANG=en objdump -s -j .interp target/release/t

target/release/t:     file format elf64-x86-64

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

将文件复制到预期的目录中,一切正常。

还有第二个选项是使用rust-musl-builder泊坞窗图像。 postgresqldiesel存在一些问题,但对于大多数项目而言,它会很好。它的工作原理是生成一个静态链接的可执行文件,您可以复制和使用它。如果您希望提供较小的docker镜像并且没有所有无用的额外数据(如解释器,未使用的库等),则此选项比使用解释器和动态库更受欢迎。

答案 1 :(得分:0)

就我而言,问题是我传递了一个无效的可执行文件名:

CMD ["liquidator"]

liquidator 是 Docker 镜像的名称,但我需要这个:

CMD ["hifi-liquidator"]

基本上 CMD 必须与 Cargo.toml 文件中的“名称”字段相同。