【问题标题】:standard_init_linux.go:219: exec user process caused: no such file or directorystandard_init_linux.go:219: exec 用户进程导致:没有这样的文件或目录
【发布时间】:2020-10-25 23:22:21
【问题描述】:

我正在尝试将我的 rust 服务器从 Heroku 移动到 Google Cloud 或 AWS。尽管我喜欢使用 git push 构建并部署到 Heroku 并仅指定一个构建包的简单性,但该服务对我来说并不划算。

我将 Google Cloud Run 和 AWS Elastic Beanstalk 确定为潜在的替代方案。

首先,我需要使用静态二进制文件构建 docker 映像。

因此,我添加了这个 Dockerfile:

FROM rust AS build
WORKDIR /usr/src
RUN rustup target add x86_64-unknown-linux-musl
RUN apt-get update && apt-get upgrade -y && apt-get install -y build-essential git clang llvm-dev libclang-dev libssl-dev pkg-config libpq-dev musl-tools brotli
RUN USER=root cargo new loxe-api
WORKDIR /usr/src/loxe-api
COPY Cargo.toml Cargo.lock ./
COPY data ./data
COPY migrations ./migrations
ENV RUSTFLAGS="-C target-feature=+crt-static" # this should be set by the target, but just to be sure
RUN cargo build --release
COPY src ./src
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV OPENSSL_INCLUDE_DIR="/usr/include/openssl"
RUN cargo install --target x86_64-unknown-linux-musl --path .

FROM scratch
COPY --from=build /usr/local/cargo/bin/loxe-api .
COPY data ./data
COPY migrations ./migrations
USER 1000
CMD ["./loxe-api"]

图像构建没有错误,但如果我通过 docker run 运行它,我会收到以下错误:

standard_init_linux.go:219: exec 用户进程导致:没有这样的文件或 目录

通过用 rust 替换最后一步的基础镜像,我检查了二进制文件和其他文件是否确实在镜像中。它们是,我可以通过ls看到它们,但我在进入shell时也无法执行loxe-api

dockerd 记录这个:

INFO[2020-07-05T13:04:42.368119033-07:00] shim containerd-shim started                  address=/containerd-shim/bf85e63468a9c1b3b9fe418b5a186673f0609bfff20c4832789ae87433e82473.sock debug=false pid=27032
INFO[2020-07-05T13:04:42.913438974-07:00] shim reaped                                   id=8cadeee800649ceca8a52d9a75cc9071b923d01a5d2a37497bf8b9a6e719267a
INFO[2020-07-05T13:04:42.925442900-07:00] ignoring event                                module=libcontainerd namespace=moby topic=/tasks/delete type="*events.TaskDelete"

这里是 Cargo.toml 的依赖部分:

[dependencies]
actix = "0.9"
actix-cors = "0.2"
actix-identity = "0.2"
actix-multipart = "0.2"
actix-rt = "1.0"
actix-web = "2.0"
argonautica = "0.2"
brotli = "3.3"
bytes = { version = "0.5", features = ["serde"]  }
chrono = { version = "0.4", features = ["serde"]  }
derive_more = "0.99"
diesel = { version = "1.4", features = ["postgres", "uuidv07", "r2d2", "chrono", "serde_json"]  }
diesel_migrations = "1.4"
dotenv = "0.15"
env_logger = "0.7"
futures = "0.3"
indexmap = { version = "1.3", features = ["serde-1"] }
lazy_static = "1.4"
log = "0.4"
openssl = { version = "0.10", features = ["vendored"] }
openssl-probe = "0.1.2"
percent-encoding = "2.1"
r2d2 = "0.8"
rand = "0.7"
redis = "0.15"
rusoto_core = { version = "0.44" }
rusoto_s3 = { version = "0.44" }
sanitize-filename = "0.2"
sendgrid = { version = "0.10", features = ["rustls"] }
serde = { version = "1.0", features = ["derive"]  }
serde_json = "1.0"
stripe-rust = "0.12"
uuid = { version = "0.8", features = ["serde", "v4"]  }
wana_kana = "2.0"

从容器内部进一步调查:

$ ldd /loxe-api
        linux-vdso.so.1 (0x00007ffcc219d000)
        libpq.so.5 => /usr/lib/x86_64-linux-gnu/libpq.so.5 (0x00007f2d3792d000)
        libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f2d3789b000)
        libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f2d375b2000)
        libgssapi_krb5.so.2 => /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f2d37565000)
        libldap_r-2.4.so.2 => /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f2d37511000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2d374f0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2d3732d000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2d37328000)
        libkrb5.so.3 => /usr/lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f2d37248000)
        libk5crypto.so.3 => /usr/lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f2d37214000)
        libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f2d3720e000)
        libkrb5support.so.0 => /usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f2d371ff000)
        libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f2d371f6000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f2d371dc000)
        liblber-2.4.so.2 => /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007f2d371cb000)
        libsasl2.so.2 => /usr/lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007f2d371ae000)
        libgnutls.so.30 => /usr/lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007f2d37002000)
        /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f2d37983000)
        libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f2d36ed1000)
        libidn2.so.0 => /usr/lib/x86_64-linux-gnu/libidn2.so.0 (0x00007f2d36eb2000)
        libunistring.so.2 => /usr/lib/x86_64-linux-gnu/libunistring.so.2 (0x00007f2d36d2e000)
        libtasn1.so.6 => /usr/lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007f2d36b1b000)
        libnettle.so.6 => /usr/lib/x86_64-linux-gnu/libnettle.so.6 (0x00007f2d36ae3000)
        libhogweed.so.4 => /usr/lib/x86_64-linux-gnu/libhogweed.so.4 (0x00007f2d36aaa000)
        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f2d36a25000)
        libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f2d36a1b000)

我还尝试从我的主机系统构建和执行。 我运行了构建二进制文件的cargo run --target x86_64-unknown-linux-musl --release,但最终导致了这个错误:

错误:无法执行进程 target/x86_64-unknown-linux-musl/release/loxe-api(从未执行)

我通过du -h target/x86_64-unknown-linux-musl/release/loxe-api检查了二进制文件的存在:

35M     target/x86_64-unknown-linux-musl/release/loxe-api

对开箱即用和一些修改过的 cross、clux/muslrust 和 emk/rust-musl-builder 存储库进行了进一步的不成功尝试。

使用 x86_64-unknown-linux-musl 目标构建和运行一个新的 cargo 默认项目是可行的。我认为,libclang、brotli 或某些 argonautica 库可能会使其无法正常工作。


这是产生相同结果的简化 Dockerfile。

FROM rust AS build
WORKDIR /usr/src

RUN rustup target add x86_64-unknown-linux-musl
RUN apt-get update && apt-get upgrade -y && apt-get install -y build-essential git clang llvm-dev libclang-dev libssl-dev pkg-config libpq-dev musl-tools brotli

RUN USER=root cargo new loxe-api
WORKDIR /usr/src/loxe-api
COPY Cargo.toml Cargo.lock ./
COPY data ./data
COPY migrations ./migrations
COPY src ./src
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV OPENSSL_INCLUDE_DIR="/usr/include/openssl"
ENV RUSTFLAGS="-C target-feature=+crt-static"
RUN cargo install --target x86_64-unknown-linux-musl --path .

FROM debian
COPY --from=build /usr/local/cargo/bin/loxe-api .
COPY .env ./.env
COPY data ./data
COPY migrations ./migrations
USER 1000
CMD ["./loxe-api"]

【问题讨论】:

  • loxe-api 是否有执行权限(与ls -l 核对)?它所在的文件系统是否有noexec 标志(检查mount)?
  • @Jmb +x 已设置。我们究竟在谈论哪个文件系统?
  • 在运行cargo build --release 之前,您确定不是要COPY src ./src 吗?似乎您也在尝试进行静态构建。您需要安装musl-gcc。恕我直言,我认为您最好使用纤薄的 Debian 映像而不是临时映像,而不必担心拥有静态二进制文件。特别是由于您有一些库依赖项,因此很难让它们通过 musl 链接。
  • musl-gcc 是 musl-tools 的一部分。我添加了一个更简单的 Dockerfile,它跳过了由于缓存原因而存在的构建步骤。 @squiguy,当我在本地构建时,我的目标/发布目录约为 ~1gb。添加实际的 docker 镜像,它会成长为能够真正快速突破 GCP Cloud Run 极限的东西。我在这里错过了什么吗?
  • 我刚刚注意到:您为 musl 目标编译 (x86_64-unknown-linux-musl),但看起来共享库是为 glibc 编译的(至少它们在 /usr/lib/x86_64-linux-gnu 中)。

标签: docker rust static-libraries static-linking musl


【解决方案1】:

虽然还是有点臃肿,但至少现在我的服务可以在 GCP Cloud Run 上运行。这就是我如何创建一个 241 mb 的 docker 镜像,我可以将它发送到不同的服务。

首先,我用 rust-argon2 替换了 aronautica 板条箱。 其次,我修改了Dockerfile:

FROM rust AS build
WORKDIR /usr/src
RUN apt-get update && apt-get upgrade -y && apt-get install -y build-essential git clang llvm-dev libclang-dev libssl-dev pkg-config libpq-dev brotli
RUN USER=root cargo new loxe-api
WORKDIR /usr/src/loxe-api
COPY Cargo.toml Cargo.lock ./
COPY data ./data
COPY migrations ./migrations
RUN cargo build --release
# Copy the source and build the application.
COPY src ./src
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV OPENSSL_INCLUDE_DIR="/usr/include/openssl"
RUN cargo install --path .

FROM debian:buster-slim
COPY --from=build /usr/local/cargo/bin/loxe-api .
# standard env
COPY .env ./.env
COPY data ./data
COPY migrations ./migrations
RUN apt-get update && apt-get install -y libssl-dev pkg-config libpq-dev brotli
CMD ["/loxe-api"]

基本上就是这样。 生成的 Docker 映像现在可以在 Google Cloud Run 上正常运行。

【讨论】:

    【解决方案2】:

    我无法按原样构建您的简化 Dockerfile,因为我没有您在 COPY 语句中引用的源文件,所以我收到“COPY failed”错误。你说“使用 x86_64-unknown-linux-musl 目标构建和运行一个新的 cargo 默认项目”,确实这个 Dockerfile(你的简化 Dockerfile 删除了 COPY 命令)对我来说很好:

    FROM rust AS build
    WORKDIR /usr/src
    
    RUN rustup target add x86_64-unknown-linux-musl
    RUN apt-get update && apt-get upgrade -y && apt-get install -y build-essential git clang llvm-dev libclang-dev libssl-dev pkg-config libpq-dev musl-tools brotli
    
    RUN USER=root cargo new loxe-api
    WORKDIR /usr/src/loxe-api
    
    ENV PKG_CONFIG_ALLOW_CROSS=1
    ENV OPENSSL_INCLUDE_DIR="/usr/include/openssl"
    ENV RUSTFLAGS="-C target-feature=+crt-static"
    RUN cargo install --target x86_64-unknown-linux-musl --path .
    
    FROM debian
    COPY --from=build /usr/local/cargo/bin/loxe-api .
    
    USER 1000
    CMD ["./loxe-api"]
    

    但是,当我构建它时,我得到了一个静态链接的可执行文件,这是我所期望的,但不是你的 ldd 输出显示的。我的ldd:

    $ ldd loxe-api 
        not a dynamic executable
    

    同样,我可以在删除 COPY 命令和注释后构建您更大的 Dockerfile,它对我来说构建得很好。

    您可能在使用 Windows 吗?您可能会遇到行尾问题,更新您的 git 配置并重新克隆您的 git 存储库可能会有所帮助。

    # update git to automatically set line ending to LF
    git config --global core.eol lf
    git config --global core.autocrlf input
    

    之后,您需要删除并重新克隆您的 git 存储库。请参阅this helpful doc from GitHub 了解更多信息。

    如果这没有帮助,请发布一些重现问题的代码。

    【讨论】:

    • 感谢您的帮助。我是linux系统,所以这个建议没有效果。关于代码,目前只有几千行代码,目前还不是真正的开源材料。也许发布的 Cargo.toml 可以提供一些线索?我真的不知道如何进一步调试。
    • @manonthemat 来自 Windows 系统的 CRLF 提交到 git repo 仍然可能是问题,即使您使用的是 Linux。设置 core.autocrlf false 而不是 input 并检查 repo 的新克隆。如果这没有帮助,请从 rust 容器内手动运行 Docker 构建步骤。 docker run -it rust bash,然后从命令行运行每个步骤,并验证您是否可以在最后运行 loxe-api
    • 没有 Windows 系统参与创建任何代码。除运行二进制文件外,所有步骤均成功。
    • @manonthemat 在cargo install 之后,ldd 对已安装的二进制文件说了什么?它应该抱怨loxe-api 不是动态可执行文件。如果它一个动态可执行文件,那么请查看您的设置和文档以找出如何使其静态链接。如果在cargo install 之后立即安装的文件被静态链接并在运行时产生“找不到文件”错误,这表明它是无法找到所需(配置、数据、迁移等)文件的可执行文件.查看它尝试打开的文件的源代码。
    • 感谢您对行尾的提醒。我收到了同样的错误消息,我正在 Windows 上开发,所以这是我的问题,尽管不是 OP 的问题。
    猜你喜欢
    • 2021-05-16
    • 2018-12-07
    • 2020-08-03
    • 2019-01-01
    • 2019-09-19
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多