Docker和“OpenSSL库在部署时报告了一个错误”

我通过亚马逊弹性容器服务通过Rust和Rocket提供API。 每当我把对象放到Amazon S3上时,它在本地工作的很好,但是如果在Amazon ECS上部署,我得到这个运行时错误:

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

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

我在错误发生的地方添加了注释:

 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上构buildDocker镜像:

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

Docker image manonthemat / muslrust本质上是clux / muslrust 。 我不得不build立自己的形象,因为我需要一个更近的夜晚生锈。

这是(简化的) Dockerfile到目前为止一直在为我工作:

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

我试图解决这个问题的一些事情….

  1. 向Cargo.toml添加了openssl = "0.9.14"

  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"] 

    这也没有改变什么,但给了我更多的select,看看里面。

  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" 

    在build立新的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 

    在那里我执行了我的项目提供了一个不同的pathSSL证书不存在没有不同的影响。

    在下一次运行中,我将其设置为指向不同的path: 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锈箱replace了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. 我在Mac上通过VirtualBox安装了Linux发行版,更新了库,安装了OpenSSL头文件和生锈,然后导入了项目。 现在我马上收到SignatureDoesNotMatch错误。 我证实我可以通过主机的vpn通过https访问Neo4j服务器,所以SSL似乎至less在部分工作。

  2. 在Amazon ECS优化的Amazon Linux AMI 2017.03.a上编译和运行项目。 build造docker形象也起作用。 从系统内部运行docker镜像不会像使用standard_init_linux.go:178: exec user process caused "no such file or directory"那样返回standard_init_linux.go:178: exec user process caused "no such file or directory"即使文件存在,拥有正确的权限,也可以对其执行其他操作等等…只是不执行它。 回滚到之前没有任何S3 / OpenSSL依赖关系的状态时也是如此。 这对于scratchalpine基本图像来说是正确的。 但是,如果我使用ubuntu作为基础镜像构builddocker镜像,则会运行预S3 / OpenSSL版本。 对于使用rusuto的版本,即使在安装OpenSSL库及其头文件时,也会出现OpenSSL错误。

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

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

我相信有办法来优化这个,我会编辑这篇文章,因为我会更多地了解这个过程,但这些都是我采取的步骤。

  1. 我在macOS上构build了这个二进制文件:

    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. 我build立了docker形象

    • 然后,我把Docker镜像推到私有仓库,并通过EC2实例上的ssh-session进行testing。 我通过docker run -e SSL_CERT_DIR=/etc/ssl/certs secretuser/secretrepo:notsosecrettag成功运行它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实例上的代理,然后重新启动这些代理。

尝试运行

update-ca-certificates图像中update-ca-certificates

喜欢:

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