【问题标题】:Docker and "The OpenSSL library reported an error" when deployed部署时 Docker 和“OpenSSL 库报告错误”
【发布时间】:2017-11-27 10:42:35
【问题描述】:

我正在通过 Rust 和 Rocket 通过 Amazon Elastic Container Service 提供 API。每当我将对象放入或获取到 Amazon S3 时,它在本地运行良好,但如果部署在 Amazon ECS 上,我会收到以下运行时错误:

HttpDispatch(HttpDispatchError { message: "The OpenSSL library reported an error" })

当我在我的机器上运行 Docker 映像时也会发生这种情况。

我已在发生错误的地方添加了 cmets:

use super::types::SomeCustomType;
use rusoto_core::{DefaultCredentialsProvider, Region, default_tls_client};
use rusoto_s3::{S3, S3Client, GetObjectRequest};

pub fn load_data_from_s3(object_name: String) -> SomeCustomType {
    let credentials = DefaultCredentialsProvider::new().unwrap();
    let client = S3Client::new(default_tls_client().unwrap(), credentials, Region::UsWest2);
    let mut request = GetObjectRequest::default();
    request.bucket = "bucket-name".to_string();
    request.key = object_name.to_string();
    match client.get_object(&request) {
        // *** This is going to fail in docker container on run-time ***
        Ok(file) => {
            // this part is actually not important for this example,
            // so code has been omitted
            someCustomType
        }
        Err(e) => {
            println!("{:?}", e); // *** errors out here! ***
            SomeCustomType::default()
        }
    }
}

Cargo.toml

[dependencies]
brotli="1.0.8"
chrono = "0.3.1"
fnv = "1.0.5"
rusted_cypher = "1.1.0"
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "614297eb9bc8fa5d9c54f653dc35b8cc3a22891f" }
rocket_codegen = { git = "https://github.com/SergioBenitez/Rocket", rev = "614297eb9bc8fa5d9c54f653dc35b8cc3a22891f" }
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "614297eb9bc8fa5d9c54f653dc35b8cc3a22891f" }
rusoto_core = "0.25.0"
rusoto_s3 = "0.25.0"
serde = "1.0.8"
serde_json = "1.0.2"
serde_derive = "1.0.8"

这就是我在 macOS 上构建 Docker 映像的方式:

cargo clean &&
docker run -v $PWD:/volume -w /volume -t manonthemat/muslrust cargo build --release &&
docker build -t dockerimagename .

Docker 镜像 manonthemat/muslrust 本质上是 clux/muslrust。我必须构建自己的镜像,因为我需要更新的 Rust 夜间构建。

这是(简化的)Dockerfile,到目前为止对我来说效果很好:

FROM scratch
ADD target/x86_64-unknown-linux-musl/release/project /
CMD ["/project"]

我尝试解决的一些问题......

  1. 已将 openssl = "0.9.14" 添加到 Cargo.toml。

  2. 将我的 Dockerfile 更改为:

    FROM alpine:edge
    
    ADD target/x86_64-unknown-linux-musl/release/project /    
    RUN apk add --no-cache curl perl openssl-dev ca-certificates linux-headers build-base zsh
    
    CMD ["/project"]
    

    这也没有改变任何东西,但给了我更多的选择。

  3. 我把cargo clean之后的交叉编译步骤改成这样:

    docker run -v $PWD:/volume -w /volume -e RUST_LOG="rusoto,hyper=debug" -e OPENSSL_STATIC=1 -e OPENSSL_DIR=/usr/local -t manonthemat/muslrust cargo build --release --features "logging"
    

    新建 docker 镜像后,获取 shell:

    docker run -i -e ROCKET_ENV=prod -e ROCKET_ADDRESS=0.0.0.0 -e RUST_LOG="rusoto,hyper=debug" dockerimagename /bin/zsh
    

    在那里,我通过为不存在的 ssl 证书提供不同的路径来执行我的项目,但没有不同的效果。

    在下一次运行中,我将其设置为指向不同的路径: SSL_CERT_DIR=/etc/ssl/certs /project 打印出 client.get_object(&request) 调用的错误时,我得到了一个有趣的结果:

    Unknown("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>...
    
  4. 我用 aws-sdk-rust crate 替换了 rusoto

thread 'main' panicked at 'Error dispatching request: HttpDispatchError { message: "the handshake failed" }', /checkout/src/libcore/result.rs:860            stack backtrace:
    0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace                                                                                                            at ./checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
    1: std::sys_common::backtrace::_print                                                                                                                                  at ./checkout/src/libstd/sys_common/backtrace.rs:71
    2: std::panicking::default_hook::{{closure}}                                                                                                                           at ./checkout/src/libstd/sys_common/backtrace.rs:60
              at ./checkout/src/libstd/panicking.rs:355
    3: std::panicking::default_hook
              at ./checkout/src/libstd/panicking.rs:371
    4: std::panicking::rust_panic_with_hook
             at ./checkout/src/libstd/panicking.rs:549
    5: std::panicking::begin_panic
             at ./checkout/src/libstd/panicking.rs:511
    6: std::panicking::begin_panic_fmt
             at ./checkout/src/libstd/panicking.rs:495
    7: rust_begin_unwind
             at ./checkout/src/libstd/panicking.rs:471
    8: core::panicking::panic_fmt
             at ./checkout/src/libcore/panicking.rs:69
    9: core::result::unwrap_failed
   10: <aws_sdk_rust::aws::s3::s3client::S3Client<P, D>>::get_object
   11: himitsu::ingest::load_data_from_s3
   12: himitsu::ingest::load_data
   13: himitsu::main
   14: __rust_maybe_catch_panic
             at ./checkout/src/libpanic_unwind/lib.rs:98
   15: std::rt::lang_start
             at ./checkout/src/libstd/panicking.rs:433
             at ./checkout/src/libstd/panic.rs:361
             at ./checkout/src/libstd/rt.rs:59
  1. 我通过 VirtualBox 在我的 Mac 上安装了 Linux 发行版,更新了库,安装了 OpenSSL 头文件和 rust,然后导入了项目。现在我马上收到 SignatureDoesNotMatch 错误。我验证了我可以通过主机的 vpn 通过 https 访问 Neo4j 服务器,因此 SSL 似乎至少可以部分工作。

  2. 在 Amazon ECS-Optimized Amazon Linux AMI 2017.03.a 上编译和运行项目可以正常工作。构建 docker 镜像也可以。从该系统中运行 docker 映像不会,因为它返回 standard_init_linux.go:178: exec user process caused "no such file or directory" 即使文件在那里,具有正确的权限,可以在其上运行其他操作等等......只是不执行它。回滚到没有任何 S3/OpenSSL 依赖项的先前状态时也是如此。这适用于scratchalpine 基本映像。但是,如果我使用 ubuntu 作为基础镜像构建 docker 镜像,我会运行 S3/OpenSSL 之前的版本。对于带有 rusuto 的版本,我会收到 OpenSSL 错误,即使在安装 OpenSSL 库及其头文件时也是如此。

  3. 在我的 Mac 上编译 Docker 映像,推送到 docker hub 的私有仓库。通过 ssh 会话将该 docker 映像拉到 EC2 实例上(与 6 中的相同)。现在运行它不会像 6 中那样给我“没有这样的文件或目录”错误,而是好的 ol'HttpDispatch(HttpDispatchError { message: "The OpenSSL library reported an error" })(现在即使将 SSL_CERTS_DIR=/etc/ssl/certs 传递到容器的环境中)

【问题讨论】:

  • 加一。带有一些代码的 docker 问题!

标签: docker amazon-s3 openssl rust rusoto


【解决方案1】:

这些是我在 AWS 上进行部署所采取的步骤。

我确信有办法对此进行优化,我将编辑这篇文章,因为我将了解有关该过程的更多信息,但这些是我已采取的步骤。

  1. 我在 macOS 上构建了二进制文件:

    docker run -v $PWD:/volume -w /volume -e RUST_LOG="rusoto,hyper=debug" -e OPENSSL_STATIC=1 -e OPENSSL_DIR=/usr/local -e SSL_CERT_DIR=/etc/ssl/certs -t manonthemat/muslrust cargo build --release --features "logging"

  2. 我修改了 Dockerfile

    FROM alpine:edge COPY target/x86_64-unknown-linux-musl/release/project / RUN apk update && apk add --no-cache pkgconfig openssl-dev ca-certificates linux-headers && update-ca-certificates CMD [ "/project" ]

  3. 我构建了 docker 镜像

    • 然后我将 docker 映像推送到私有存储库,并通过 EC2 实例上的 ssh-session 将其拉出以进行测试。我通过docker run -e SSL_CERT_DIR=/etc/ssl/certs secretuser/secretrepo:notsosecrettag
    • 成功运行了它
  4. 我标记了 docker 映像并将其推送到 AWS 存储库

  5. 为了在 Amazon Elastic Container Service 上成功运行,我必须修改任务定义。在 containerDefinitions 中,我必须增加内存并将其添加到环境数组中:

    `{
      "name": "SSL_CERT_DIR",
      "value": "/etc/ssl/certs"
    }`
    
  6. 由于某些未知且可能不相关的原因,我还必须更新 EC2 实例上的代理,然后重新启动它们。

【讨论】:

    【解决方案2】:

    尝试运行

    图片中的update-ca-certificates

    喜欢:

    FROM scratch
    ADD target/x86_64-unknown-linux-musl/release/project /
    RUN update-ca-certificates
    CMD ["/project"]
    

    【讨论】:

    • 在哪一步?对于使用FROM scratch 的原始方法,没有地方可以这样做,因为没有/bin/sh 甚至可以执行update-ca-certificates。如果插入假设是从 Alpine 构建的 docker 映像,那么运行 update-ca-certificates 仍然与我遇到的 standard_init_linux.go:178: exec user process caused "no such file or directory" 错误无关。
    • 您始终可以在运行脚本之前添加该步骤。
    • 从头开始是你自己构建的图像,缩小层,调试你应该使用原始图像
    • 如果我所做的只是编译二进制文件,那“原始图像”会是什么?原始图像是“scratch”。要么你没有阅读整篇文章,要么你需要在你的答案中多加一点解释,因为我不确定你想在这里给我什么样的好建议。
    • 'scratch' 来自哪里?你建造了它,或者它缺少了一些东西。因此,您可以从二进制文件的原始版本开始,或者您自己制作。我的建议是您需要在运行脚本之前运行update-ca-certificates。即使使用二进制文件,您也可以添加RUN update-ca-certificates 命令。在您的入口点之前。见编辑
    猜你喜欢
    • 2022-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    相关资源
    最近更新 更多