rust-openssl:找不到 OpenSSL 安装目录

Qwe*_*tie 21 openssl rust docker

我正在尝试在 docker 中编译 rust 二进制文件,但编译失败,提示尽管安装了 openssl,但未找到 openssl。其他答案表明安装pkg-configlibssl-dev安装可以解决问题,但它们已经安装了。我相信这个问题与交叉编译有关,因为我能够在主机和目标相同时构建此映像。

Dockerfile:

FROM rust:1.57.0 AS build
WORKDIR /usr/src

RUN rustup target add x86_64-unknown-linux-musl

RUN USER=root cargo new project
WORKDIR /usr/src/project
COPY Cargo.toml Cargo.lock ./
RUN apt-get update \
&& apt-get upgrade \
&& apt-get install -y cmake pkg-config libssl-dev
RUN cargo build --release
Run Code Online (Sandbox Code Playgroud)

错误:

#18 14.01    Compiling openssl-sys v0.9.72
#18 14.17 error: failed to run custom build command for `openssl-sys v0.9.72`
#18 14.18 
#18 14.18 Caused by:
#18 14.18   process didn't exit successfully: `/usr/src/project/target/release/build/openssl-sys-64e55e6c4223d7aa/build-script-main` (exit status: 101)
#18 14.18   --- stdout
#18 14.18   cargo:rustc-cfg=const_fn
#18 14.18   cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR
#18 14.18   X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR unset
#18 14.18   cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
#18 14.18   OPENSSL_LIB_DIR unset
#18 14.18   cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR
#18 14.18   X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR unset
#18 14.18   cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
#18 14.18   OPENSSL_INCLUDE_DIR unset
#18 14.18   cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR
#18 14.18   X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR unset
#18 14.18   cargo:rerun-if-env-changed=OPENSSL_DIR
#18 14.18   OPENSSL_DIR unset
#18 14.18   cargo:rerun-if-env-changed=OPENSSL_NO_PKG_CONFIG
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64-unknown-linux-musl
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64_unknown_linux_musl
#18 14.18   cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-musl
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_musl
#18 14.18   cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-musl
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_musl
#18 14.18   cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
#18 14.18   cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
#18 14.18   run pkg_config fail: "pkg-config has not been configured to support cross-compilation.\n\nInstall a sysroot for the target platform and configure it via\nPKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a\ncross-compiling wrapper for pkg-config and set it via\nPKG_CONFIG environment variable."
#18 14.18 
#18 14.18   --- stderr
#18 14.18   thread 'main' panicked at '
#18 14.18 
#18 14.18   Could not find directory of OpenSSL installation, and this `-sys` crate cannot
#18 14.18   proceed without this knowledge. If OpenSSL is installed and this crate had
#18 14.18   trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
#18 14.18   compilation process.
#18 14.18 
#18 14.18   Make sure you also have the development packages of openssl installed.
#18 14.18   For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.
#18 14.18 
#18 14.18   If you're in a situation where you think the directory *should* be found
#18 14.18   automatically, please open a bug at https://github.com/sfackler/rust-openssl
#18 14.18   and include information about your system as well as this message.
#18 14.18 
#18 14.18   $HOST = aarch64-unknown-linux-gnu
#18 14.18   $TARGET = x86_64-unknown-linux-musl
#18 14.18   openssl-sys = 0.9.72
#18 14.18 
#18 14.18   ', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.72/build/find_normal.rs:180:5
Run Code Online (Sandbox Code Playgroud)

Gra*_*dpa 14

您是正确的,该问题与交叉编译有关。您正在 Debian 容器上进行编译,并且它没有可供编译的 MUSL 库。

您有两个选择:

  1. 告诉 Rust openssl crate 编译供应商的 openssl。
  2. 在 Alpine 容器上编译。

选项 1:使用供应的 openssl

假设我们从reqwest 的示例开始:

use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::get("https://httpbin.org/ip")
        .await?
        .json::<HashMap<String, String>>()
        .await?;
    println!("{:#?}", resp);
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

并且 Cargo.toml 具有依赖项:

[dependencies]
reqwest = { version = "0.11", features = ["json"] }
tokio = { version = "1", features = ["full"] }
Run Code Online (Sandbox Code Playgroud)

我们从一个合理的默认 Dockerfile 开始:

FROM rust:latest as build

RUN rustup target add x86_64-unknown-linux-musl
RUN apt-get update && apt-get install -y musl-tools

COPY . /app
WORKDIR /app

RUN cargo build --target=x86_64-unknown-linux-musl --release
Run Code Online (Sandbox Code Playgroud)

当我们用它构建这个时,docker build .我们会得到与您看到的相同的错误。

[dependencies]解决方案是在 Cargo.toml 中添加以下行:

openssl = { version = "0.10", features = ["vendored"] }
Run Code Online (Sandbox Code Playgroud)

这使得opensslcrate 为目标编译 C 库本身x86_64-unknown-linux-musl

请注意,无需安装libssl-devpkg-config在构建容器中。

选项 2:使用 Alpine 容器构建

通过在 Alpine 容器上编译,可以完全避免交叉编译问题。

使用 Cargo.toml 中的原始依赖项:

FROM rust:latest as build

RUN rustup target add x86_64-unknown-linux-musl
RUN apt-get update && apt-get install -y musl-tools

COPY . /app
WORKDIR /app

RUN cargo build --target=x86_64-unknown-linux-musl --release
Run Code Online (Sandbox Code Playgroud)

您可以使用以下 Dockerfile 进行构建:

FROM rust:1.68-alpine as builder

RUN apk add openssl-dev musl-dev

COPY . /app
WORKDIR /app

RUN cargo build --release
Run Code Online (Sandbox Code Playgroud)

我们安装openssl-dev在 Alpine 中,这样 openssl crate 就不必从源代码编译库,并且我们安装musl-dev它可以链接到 C 运行时。


aak*_*dev 5

你忘记了须藤

sudo apt-get update
sudo apt-get install libssl-dev
Run Code Online (Sandbox Code Playgroud)