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"]
我试图解决这个问题的一些事情….
-
向Cargo.toml添加了
openssl = "0.9.14"
。 -
将我的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,看看里面。
-
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>...
-
我用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
-
我在Mac上通过VirtualBox安装了Linux发行版,更新了库,安装了OpenSSL头文件和生锈,然后导入了项目。 现在我马上收到SignatureDoesNotMatch错误。 我证实我可以通过主机的vpn通过https访问Neo4j服务器,所以SSL似乎至less在部分工作。
-
在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依赖关系的状态时也是如此。 这对于scratch
和alpine
基本图像来说是正确的。 但是,如果我使用ubuntu
作为基础镜像构builddocker镜像,则会运行预S3 / OpenSSL版本。 对于使用rusuto的版本,即使在安装OpenSSL库及其头文件时,也会出现OpenSSL错误。 -
在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上进行部署的步骤。
我相信有办法来优化这个,我会编辑这篇文章,因为我会更多地了解这个过程,但这些都是我采取的步骤。
-
我在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"
-
我修改了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" ]
-
我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
- 然后,我把Docker镜像推到私有仓库,并通过EC2实例上的ssh-session进行testing。 我通过
-
我将Docker镜像标记并推送到AWS存储库
-
为了成功运行Amazon Elastic Container Service,我必须修改任务定义。 在containerDefinitions我不得不把内存,并将其添加到环境数组:
`{ "name": "SSL_CERT_DIR", "value": "/etc/ssl/certs" }`
-
对于一些未知和可能不相关的原因,我还必须更新EC2实例上的代理,然后重新启动这些代理。
尝试运行
update-ca-certificates
图像中update-ca-certificates
喜欢:
FROM scratch ADD target/x86_64-unknown-linux-musl/release/project / RUN update-ca-certificates CMD ["/project"]