从 Docker 临时镜像构建 Rust 服务容器时出现问题

2024-03-06

我有一个 Rust 二进制文件,想在容器中运行。当我使用时效果很好ubuntu甚至gcr.io/distroless/cc作为基本图像,但是当我尝试从scratch图像,我遇到了一些问题。这显然是因为某些文件预计位于不存在的文件系统上。我能够弄清楚如何安装 CA 根证书,但现在我收到了一个不同的错误,似乎是在二进制文件尝试进行 DNS 查找时发生的。

我的 Dockerfile 看起来大多像这样(我删除了一些构建优化):

FROM rust:latest as cargo-build

WORKDIR /build
ENV RUSTFLAGS="-C target-feature=+crt-static"

COPY aggregator/ ./

RUN cargo build --release --target x86_64-unknown-linux-gnu

#####################################

FROM alpine:3.6 as ca-certificates
RUN apk add -U --no-cache ca-certificates

#####################################

FROM scratch

COPY --from=cargo-build /build/target/x86_64-unknown-linux-gnu/release/aggregator /entrypoint
COPY --from=ca-certificates /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

ENTRYPOINT [ "/entrypoint" ]

运行时(从 Rust 二进制文件)出现的错误是:

Error: Failed to load job description from S3

Caused by:
    0: io error: error trying to connect: dns error: Device or resource busy (os error 16)
    1: io error: error trying to connect: dns error: Device or resource busy (os error 16)
    2: error trying to connect: dns error: Device or resource busy (os error 16)
    3: dns error: Device or resource busy (os error 16)
    4: Device or resource busy (os error 16)

我用 Google 搜索了该错误,并找到了另一个具有相同错误的 Rust/Docker 项目,但他们通过从scratch to gcr.io/distroless/cc作为基本图像,我想通过了解问题所在来避免这种情况。

查看文件系统,它似乎具有最小的网络配置,但我可能是错的。

.
├── dev
│   ├── console
│   ├── pts
│   └── shm
├── entrypoint
├── etc
│   ├── hostname
│   ├── hosts
│   ├── mtab -> /proc/mounts
│   ├── resolv.conf
│   └── ssl
│       └── certs
│           └── ca-certificates.crt
├── proc
└── sys

就像我写的那样,这与其他基本映像一起工作得很好,那么我缺少什么来让网络 Rust 二进制文件从“从头开始”运行呢?


我遇到了同样的问题。该问题可能是由您的代码中尝试调用getaddrinfo https://linux.die.net/man/3/getaddrinfo系统函数,除非系统上存在一些额外的共享库,否则该函数将无法工作。

对我来说,罪魁祸首是 Reqwest 使用的 Hyper。超级用途getaddrinfo默认情况下解析 DNS 名称。

有两种可能的解决方案:

  1. 将必要的库复制到您的映像中。这个答案 https://stackoverflow.com/a/68409203/7099148建议您需要复制什么,但我还没有尝试过。
  2. 确保您完全使用 Rust 代码解析主机名。

对于第二个选项,您可以使用trust_dns_resolver https://docs.rs/trust-dns-resolver/latest/trust_dns_resolver/图书馆作为替代品getaddrinfo。如果您使用 Reqwest(就像我一样),您可以通过启用trust-dns https://docs.rs/reqwest/0.11.10/reqwest/#optional-features功能于reqwest crate.

If you're using Hyper directly, it looks like it's a bit more tricky. You need to create an implementation of Service https://docs.rs/hyper/0.14.19/hyper/service/trait.Service.html<dns::Name https://docs.rs/hyper/0.14.19/hyper/client/connect/dns/struct.Name.html> to use as an alternative to Hyper's default GaiResolver https://docs.rs/hyper/0.14.19/hyper/client/connect/dns/struct.GaiResolver.html. To get started, you can see (or copy) how Reqwest does it here https://github.com/seanmonstar/reqwest/blob/master/src/dns.rs. Update: Looks like the hyper-trust-dns https://docs.rs/crate/hyper-trust-dns/latest crate is what you want in this scenario.

Note:如果您使用 TLS/HTTPS,您的程序在尝试使用 Openssl 时可能会遇到类似的问题。您可以类似地使用“内部”移动 TLS 内容rustls https://docs.rs/rustls/0.20.6/rustls/。对于 Reqwest,您可以使用rustls-tls https://docs.rs/reqwest/0.11.10/reqwest/#optional-features功能标志以及default-features = false。您还可以查看自己的相处情况native-tls-vendored https://docs.rs/reqwest/0.11.10/reqwest/#optional-features反而。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Docker 临时镜像构建 Rust 服务容器时出现问题 的相关文章

随机推荐