muslrust icon indicating copy to clipboard operation
muslrust copied to clipboard

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

Open KonradHoeffner opened this issue 2 years ago • 11 comments

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 [email protected]: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:

  • looking at the muslrust Dockerfile, it is based on Ubuntu Jammy, not on Alpine
  • the error occurs inside a muslrust container
  • inside an official Rust container, the errors occurs with a binary built within a muslrust container but not with a binary built within an official Rust container

KonradHoeffner avatar Aug 04 '23 08:08 KonradHoeffner

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.

clux avatar Aug 04 '23 12:08 clux