【发布时间】:2022-06-20 19:37:53
【问题描述】:
我有一个想要在容器中运行的 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)
我用谷歌搜索了这个错误,并能够找到另一个具有相同错误的 Rust/Docker 项目,但他们通过从 scratch 切换到 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 二进制文件从“零开始”运行?
【问题讨论】:
-
你不需要用 Alpine 镜像编译你的 Rust 程序,因为你使用 Alpine 来提供其他组件吗?我不认为他们会兼容。
-
不,它只是一个依赖项查找的文件。 Rust 将 libc 和 openssl 静态编译到二进制文件中,但它不包括那些库期望出现在文件系统中的文件,通常在“/etc”中。我原以为 DNS 所需的所有 libc 都是 resolv .conf,但似乎并非如此......
-
您正在使用 x86_64-unknown-linux-gnu 构建,它仍然需要链接 glibc 等。您是否尝试过使用 musl 目标构建以获得完全静态的二进制文件?
-
不,但如果我理解正确,
RUSTFLAGS="-C target-feature=+crt-static"确实使我的应用程序完全静态。至少,在它上面运行ldd告诉我它不是动态链接的二进制文件,并且没有列出任何依赖项。