clux / muslrust

Docker environment for building musl based static linux rust binaries
MIT License
965 stars 88 forks source link

DNS errors in binaries built with muslrust when run in rootless Docker #122

Open KonradHoeffner opened 1 year ago

KonradHoeffner commented 1 year ago

Certain domains (for me it's github.com) always fail to resolve in rootless Docker when the image is built with muslrust:

main.rs

use std::net::ToSocketAddrs;

fn main() {
    let domains = ["google.com", "github.com"];
    for domain in domains
    {
        println!("Trying to resolve {domain} with to_socket_addrs()");
        format!("{domain}:443").to_socket_addrs().unwrap();
        println!("it worked");
    }
}

There are no dependencies installed.

Dockerfile

# syntax=docker/dockerfile:1
FROM clux/muslrust:1.71.0 as musl
#USER root
WORKDIR /app
COPY . .
ARG CARGO_INCREMENTAL=0
# trying to resolve URLs, just show errors, don't abort
# this *works* in rootless Docker in musl
RUN curl -sS -o /dev/null https://google.com; exit 0
# this *fails* in rootless Docker in musl
RUN curl -sS -o /dev/null https://github.com; exit 0
RUN cargo build --release --target x86_64-unknown-linux-musl
CMD ["/app/target/x86_64-unknown-linux-musl/release/mwedns"]

FROM rust:1.71.0-slim
WORKDIR /app
COPY . .
ARG CARGO_INCREMENTAL=0
# this *works* in rootless Docker with the official Rust image
RUN curl -sS -o /dev/null https://google.com; exit 0
# this *works* in rootless Docker with the official Rust image
RUN curl -sS -o /dev/null https://github.com; exit 0
RUN cargo build --release
COPY --link --from=musl /app/target/x86_64-unknown-linux-musl/release/mwedns /app/musl
# run the one compiled with the official Rust image first
CMD echo "official Rust" && /app/target/release/mwedns && echo "musl Rust" && /app/musl

You can test this MWE at https://github.com/KonradHoeffner/mwedns:

$ git clone git@github.com:KonradHoeffner/mwedns.git
$ cd mwedns
$ docker build . -t mwedns
[...]
$ docker run --rm mwedns

Output

official Rust
Trying to resolve google.com with to_socket_addrs()
it worked
Trying to resolve github.com with to_socket_addrs()
it worked
musl Rust
Trying to resolve google.com with to_socket_addrs()
it worked
Trying to resolve github.com with to_socket_addrs()
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: Uncategorized, error: "failed to lookup address information: Name does not resolve" }', src/main.rs:8:51

I reported this first at https://github.com/algesten/ureq/issues/645 but then found out it has nothing to do with ureq.

You can also verify that DNS lookup fails in rootless Docker with:

$ docker run --rm --entrypoint "/bin/bash" clux/muslrust:1.71.0 -c "curl -sS -o /dev/null https://github.com"
curl: (6) Could not resolve host: github.com

Relation to Alpine?

There is a known bug with the Alpine image reported at https://github.com/alpinelinux/docker-alpine/issues/155. However the things that differ here:

clux commented 1 year ago

This is almost certainly down to how musl does dns and not something we can solve here.

You are putting a musl built static binary inside of a rust container which is a debian based (glibc) distro, with dns resolution settings (resolv.conf / dnsmasq.conf) that is probably not ideal for what it was built for.

I would recommend following this post and seeing where that takes you. There's also a more kubernetes focused issue that may be useful at https://github.com/k3s-io/k3s/issues/6132.