astral-sh / uv

An extremely fast Python package and project manager, written in Rust.
https://docs.astral.sh/uv
Apache License 2.0
23.18k stars 667 forks source link

Uv install script cannot detect glibc inside WolfiOS base image. #7903

Open KhazAkar opened 2 weeks ago

KhazAkar commented 2 weeks ago

When trying to install uv inside container with cURL'd script, when using wolfi-base from chainguard, cannot detect glibc version.

#8 [stage-0 4/7] RUN curl -LsSf https://astral.sh/uv/install.sh >install.sh && sh install.sh
#8 9.598 head: /proc/self/exe: Bad file descriptor
#8 9.645 ERROR: unknown platform bitness
#8 9.647 sh: bad number
#8 9.653 install.sh: line 911: ldd: not found
#8 9.701 System glibc version (`') is too old; checking alternatives
#8 9.814 downloading uv 0.4.18 aarch64-unknown-linux-musl-static
#8 38.24 installing to /home/nonroot/.cargo/bin
#8 38.34   uv
#8 38.39   uvx
#8 38.39 everything's installed!
#8 38.79 
#8 38.80 To add $HOME/.cargo/bin to your PATH, either restart your shell or run:
#8 38.80 
#8 38.80     source $HOME/.cargo/env (sh, bash, zsh)
#8 38.80     source $HOME/.cargo/env.fish (fish)
#8 DONE 38.9s

(slow because I'm building aarch64 container on x86 host) It installs musl python variant, when it's glibc here. More info about Wolfi OS - https://github.com/wolfi-dev

mistydemeo commented 2 weeks ago

Looks like the inability to detect glibc comes from ldd being missing; I'll look into adding support for other methods to detect the glibc version. The "unable to detect bitness" one is interesting - I hadn't expected us not to have access to /proc/self/exe.

KhazAkar commented 2 weeks ago

Probably because access to it was removed or restricted as part of WolfiOS security model, around which they revolve whole "OS" around. Like secured to the brim alpine with glibc instead of musl.

mistydemeo commented 2 weeks ago

I've been doing some local testing and wasn't able to reproduce the /proc/self/exe issue, though I can reproduce the ldd issue. Any chance you're able to share what the previous steps in your dockerfile look like?

KhazAkar commented 2 weeks ago

Sure, no problem, I can share even whole Dockerfile. Adding posix-libc-utils fixes missing ldd and now glibc is detected.

FROM cgr.dev/chainguard/wolfi-base:latest
RUN apk add curl build-base posix-libc-utils
USER nonroot
WORKDIR /home/nonroot
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
RUN mkdir -p .cache/uv
RUN curl -LsSf https://astral.sh/uv/install.sh >install.sh && sh install.sh
ENV PATH="/home/nonroot/.cargo/bin:/home/nonroot/app/.venv/bin:$PATH"
RUN uv python install 3.11.9 && uv venv
RUN --mount=type=cache,target=/root/.cache/uv \
    --mount=type=bind,source=uv.lock,target=uv.lock \
    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    CC=gcc uv sync --frozen --no-install-project --no-dev
COPY app .
EXPOSE 19110
ENTRYPOINT []
CMD ["fastapi", "--host", "0.0.0.0", "--port", "19110", "/home/nonroot/app"]
KhazAkar commented 2 weeks ago

Interesting observation on the side - if I use /root/.cache/uv - step with mount works fine. If I want target cache to be in /home/nonroot/.cache/uv - it doesn't work with 'permission denied' error. Either I don't understand how something works, or is a bug.

konstin commented 1 week ago

A few notes from my end: It would be great if we could correctly detect this (https://github.com/axodotdev/cargo-dist/issues/1439), the difficulty is that the curl installer is a shell script which limits our options a bit (uv itself uses a rust crate to do ELF parsing of common binaries).

Both the musl and the glibc build should generally work equally (we don't load any shared libraries), the fallback here should work without disadvantages.

In docker, we generally recommend for installation:

COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

The image is built from a scratch base and ships only the binaries:

$ docker create --name="tmp_$$" ghcr.io/astral-sh/uv:latest
3e25e2a9b7487d271792ac87aad50c2b4f09eb3b55cbc0ee317654a68a473e1b
$ docker export tmp_$$ | tar t
.dockerenv
dev/
dev/console
dev/pts/
dev/shm/
etc/
etc/hostname
etc/hosts
etc/mtab
etc/resolv.conf
io/
proc/
sys/
uv
uvx