代码之家  ›  专栏  ›  技术社区  ›  VP.

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

  •  17
  • VP.  · 技术社区  · 8 年前

    我试图用我的二进制文件(用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"
    

    我不知道该怎么办。我觉得这个错误消息很奇怪。根据 official Docker documentation 它必须起作用。

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

    Docker version 18.02.0-ce, build fc4de447b5
    

    我用一个C++程序进行了测试,它在clang和gcc中都运行良好。

    它不适用于 scratch , alpine , busybox 或 bash -基于图像,但它确实适用于 postgresql , ubuntu 和 debian 图像。确切的问题与生锈和轻量级docker图像有关,否则一切正常。

    2 回复  |  直到 8 年前
        1
  •  17
  •   Shepmaster Tim Diekmann    8 年前

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

    这可能有点令人困惑,因为许多听说过Rust的人也听说过Rust二进制文件是静态链接的,但这指的是板条箱中的Rust代码:板条箱是静态链接的,因为它们在编译时都是已知的。这并不引用程序可能链接到的现有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 docker图像。有一些问题 postgresql 和 diesel 但对于大多数项目来说,这将是一件好事。它的工作原理是生成一个静态链接的可执行文件,您可以复制并使用它。如果您想提供尺寸较小的docker映像,并且不需要所有无用的额外数据(如解释器、未使用的库等),则此选项比使用解释器和动态库更受欢迎。

        2
  •  0
  •   Paul Razvan Berg    5 年前

    在我的情况下,问题是我传递了一个无效的可执行文件名:

    CMD ["liquidator"]
    

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

    CMD ["hifi-liquidator"]
    

    基本上,CMD必须与 Cargo.toml 文件

    推荐文章