代码之家  ›  专栏  ›  技术社区  ›  opensourcegeek

Rust Musl Docker图像找不到货物

  •  0
  • opensourcegeek  · 技术社区  · 5 年前

    我想让铁锈在Docker中运行,以用于32位MUSL构建。自从我更新它以使用新的url来拉rustup之后,在使用bash以交互方式运行容器时遇到了这个问题:

    root@2c3549fe3169:/sample# cargo
    error: command failed: 'cargo'
    info: caused by: No such file or directory (os error 2)
    

    奇怪的是,我能看到可执行文件

    root@2c3549fe3169:/sample# ls -l /root/.cargo/bin/
    total 101440
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 cargo
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 cargo-clippy
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 cargo-fmt
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rls
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rust-gdb
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rust-lldb
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rustc
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rustdoc
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rustfmt
    -rwxr-xr-x 10 root root 10383380 Feb 17 21:34 rustup
    root@2c3549fe3169:/sample# date
    Sun Feb 17 21:34:21 UTC 2019
    root@2c3549fe3169:/sample# file /root/.cargo/bin/cargo
    /root/.cargo/bin/cargo: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.9, with debug_info, not stripped
    root@2c3549fe3169:/sample# cargo
    error: command failed: 'cargo'
    info: caused by: No such file or directory (os error 2)
    

    通过以下方式安装:

    RUN curl https://sh.rustup.rs -sSf | sh -s -- \
    --default-toolchain 1.32.0 \
    -y && \
    ~/.cargo/bin/rustup target add i686-unknown-linux-musl && \
    echo "[build]\ntarget = \"i686-unknown-linux-musl\"" > ~/.cargo/config
    

    我可以看到文件,但似乎无法运行,即使切换到该目录:

    root@2c3549fe3169:~/.cargo/bin# ./cargo
    error: command failed: 'cargo'
    info: caused by: No such file or directory (os error 2)
    

    这就是我跑步时看到的 ldd :

    root@4e21c8d37266:/volume# ldd /root/.cargo/bin/cargo
    linux-gate.so.1 (0xf7f41000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xf774c000)
    librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xf7742000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xf7723000)
    libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xf7705000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7529000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf7427000)
    /lib/ld-linux.so.2 (0xf7f43000)
    

    这是我完整的档案

    FROM i386/ubuntu
    
    RUN apt-get update && apt-get install -y \
      cmake \
      curl \
      file \
      git \
      g++ \
      python \
      make \
      nano \
      ca-certificates \
      xz-utils \
      musl-tools \
      pkg-config \
      apt-file \
      xutils-dev \
      --no-install-recommends && \
      rm -rf /var/lib/apt/lists/*
    
    
    RUN curl https://sh.rustup.rs -sSf | sh -s -- \
      --default-toolchain 1.32.0 \
      -y && \
      ~/.cargo/bin/rustup target add i686-unknown-linux-musl && \
      echo "[build]\ntarget = \"i686-unknown-linux-musl\"" > ~/.cargo/config
    
    
    # Compile C libraries with musl-gcc
    ENV SSL_VER=1.0.2j \
        CURL_VER=7.52.1 \
        CC=musl-gcc \
        PREFIX=/usr/local \
        PATH=/usr/local/bin:$PATH \
        PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
    
    RUN curl -sL http://www.openssl.org/source/openssl-$SSL_VER.tar.gz | tar xz && \
        cd openssl-$SSL_VER && \
        ./Configure no-shared --prefix=$PREFIX --openssldir=$PREFIX/ssl no-zlib -m32 linux-elf -fPIC -fno-stack-protector && \
        make depend 2> /dev/null && make -j$(nproc) && make install && \
        cd .. && rm -rf openssl-$SSL_VER
    
    RUN curl https://curl.haxx.se/download/curl-$CURL_VER.tar.gz | tar xz && \
        cd curl-$CURL_VER && \
        ./configure --enable-shared=no --enable-static=ssl --enable-optimize --prefix=$PREFIX --host=i686-pc-linux-gnu CFLAGS=-m32 \
          --with-ca-path=/etc/ssl/certs/ --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt --without-ca-fallback && \
        make -j$(nproc) && make install && \
        cd .. && rm -rf curl-$CURL_VER
    
    ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
        SSL_CERT_DIR=/etc/ssl/certs \
        OPENSSL_LIB_DIR=$PREFIX/lib \
        OPENSSL_INCLUDE_DIR=$PREFIX/include \
        OPENSSL_DIR=$PREFIX \
        OPENSSL_STATIC=1 \
        PATH=/usr/local/bin:/root/.cargo/bin:$PATH
    
    RUN echo $PATH
    
    

    然后离开 cargo 按注释的二进制:

    root@156da6108ff8:~/.cargo/bin# strace -f -e trace=execve cargo               
    execve("/root/.cargo/bin/cargo", ["cargo"], 0xfffdd8fc /* 20 vars */) = 0
    execve("/root/.rustup/toolchains/1.32.0-x86_64-unknown-linux-gnu/bin/cargo", ["/root/.rustup/toolchains/1.32.0-"...], 0x57d95620 /* 25 vars */) = -1 ENOENT (No such file or directory)
    error: command failed: 'cargo'
    info: caused by: No such file or directory (os error 2)
    +++ exited with 1 +++
    
    0 回复  |  直到 5 年前
        1
  •  3
  •   Danila Kiver    5 年前

    这是我们调查的总结。

    用于构建的基本映像是 i386/ubuntu 但是,在32位环境中,此图像不会适当地屏蔽 uname(2) 打电话给 setarch linux32 作为入口点),因此,当在64位系统(您的情况)上运行时,构建容器中的任何进程都将调用 未命名(2) uname(1) 看到 x86_64 而不是 i686 . 这就是问题的根源。

    安装时 cargo ,您将下载并运行安装脚本,该脚本将检测运行它的平台并下载 rustup-init . 此脚本中的平台检测正确地识别出它在32位环境中运行,但在64位内核上运行,因此该脚本下载32位版本的 RuSTUP初始化 . 然而, RuSTUP初始化 决定继续 X86Y64 (可能它看到了 X86Y64 返回的 未命名(2) ,但不执行“64位内核上的32位环境”检查,就像安装程序脚本那样)。在安装过程中可以看到 -y :

    Current installation options:
    
        default host triple: x86_64-unknown-linux-gnu
        default toolchain: stable
        modify PATH variable: yes
    

    所以, rustup 安装64位工具链,在调用 货物 运行结果 32位环境中的64位二进制文件 ,所以你看到了错误。

    我仍然感觉到一些不一致的行为,因为安装脚本和 RuSTUP初始化 parts of the same project 我不明白他们为什么要检测平台 不同地 在相同的环境中(为什么不能 RuSTUP初始化 就跟安装脚本一样聪明吧?).

    正如@shepmaster注意到的,这是一个已知的问题( Rustup installs 64bit compiler on a 32bit Docker instance )有两种可能的解决方法:

    • 通过传递 --default-host i686-unknown-linux-gnu 安装人员;
    • 在下面运行安装程序 Setarch Linux32型 所以它的使命 未命名(2) 将看到 I166 而不是 X86Y64 .

    就我个人而言,我会选择第一个选项,因为它似乎不那么老套。