Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

linux - Docker Alpine executable binary not found even if in PATH

I have an alpine running container which contains some binaries in usr/local/bin

When I ls the content of usr/local/bin I got this output :

/usr/local/bin # ls
dwg2SVG     dwg2dxf     dwgadd      dwgbmp      dwgfilter   dwggrep     dwglayers   dwgread     dwgrewrite  dwgwrite    dxf2dwg     dxfwrite

Which is what I expected. However if I execute one of these binaries by calling it I got a not found error from the shell :

/usr/local/bin # dwg2dxf
sh: dwgread: not found
/usr/local/bin # ./dwg2dxf
sh: ./dwgread: not found

I tested my $PATH which seems to be correct :

/usr/local/bin # echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

How can I make those binaries callable or "foundable" ? Did I miss something in my Dockerfile build ? I suppose that there is something with the ldconfig command in alpine that went wrong but I'm not sure.

EDIT

As suggested in one answer here I executed the file command and here is the output :

/usr/local/bin # file dwg2dxf
dwgread: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=7835d4a42651a5fb7bdfa2bd8a76e40096bacb07, with debug_info, not stripped

Thoses binaries are from the LibreDWG Official repository as well as the first part of my Dockerfile. Here is the complete Dockerfile :

# podman/docker build -t libredwg .
############################
# STEP 1 build package from latest tar.xz
############################

FROM python:3.7.7-buster AS extracting
# libxml2-dev is broken so we need to compile it by our own
ARG LIBXML2VER=2.9.9
RUN apt-get update && 
    apt-get install -y --no-install-recommends autoconf libtool swig texinfo 
            build-essential gcc libxml2 python3-libxml2 libpcre2-dev libpcre2-32-0 curl 
            libperl-dev libxml2-dev && 
    mkdir libxmlInstall && cd libxmlInstall && 
    wget ftp://xmlsoft.org/libxml2/libxml2-$LIBXML2VER.tar.gz && 
    tar xf libxml2-$LIBXML2VER.tar.gz && 
    cd libxml2-$LIBXML2VER/ && 
    ./configure && 
    make && 
    make install && 
    cd /libxmlInstall && 
    rm -rf gg libxml2-$LIBXML2VER.tar.gz libxml2-$LIBXML2VER
WORKDIR /app
RUN tarxz=`curl --silent 'https://ftp.gnu.org/gnu/libredwg/?C=M;O=D' | grep '.tar.xz<' | 
         head -n1|sed -E 's/.*href="([^"]+)".*/1/'`; 
    echo "latest release $tarxz"; 
    curl --silent --output "$tarxz" https://ftp.gnu.org/gnu/libredwg/$tarxz && 
    mkdir libredwg && 
    tar -C libredwg --xz --strip-components 1 -xf "$tarxz" && 
    rm "$tarxz" && 
    cd libredwg && 
    ./configure --disable-bindings --enable-release && 
    make -j `nproc` && 
    mkdir install && 
    make install DESTDIR="$PWD/install" && 
    make check DOCKER=1 DESTDIR="$PWD/install"

############################
# STEP 2 install into stable-slim
############################

# pull official base image
FROM osgeo/gdal:alpine-normal-latest

# set work directory
WORKDIR /usr/src/app



# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# copy requirements file
COPY ./requirements.txt /usr/src/app/requirements.txt

# install dependencies
RUN set -eux 
    && apk add --no-cache --virtual .build-deps build-base 
        py3-pip libressl-dev libffi-dev gcc musl-dev python3-dev postgresql-dev
    && pip3 install --upgrade pip setuptools wheel 
    && pip3 install -r /usr/src/app/requirements.txt 
    && rm -rf /root/.cache/pip

# Install libredwg binaries
COPY --from=extracting /app/libredwg/install/usr/local/bin/* /usr/local/bin/
COPY --from=extracting /app/libredwg/install/usr/local/include/* /usr/local/include/
COPY --from=extracting /app/libredwg/install/usr/local/lib/* /usr/local/lib/
COPY --from=extracting /app/libredwg/install/usr/local/share/* /usr/local/share/
RUN ldconfig /usr/local/bin/
RUN ldconfig /usr/local/include/
RUN ldconfig /usr/local/lib/
RUN ldconfig /usr/local/share/

# copy project
COPY . /usr/src/app/
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

On Alpine Linux, the not found error is a typical symptom of dynamic link failure. It is indeed a rather confusing error by musl's ldd linker.

Most of the world Linux software is linked against glibc, the GNU libc library (libc provides the standard C library and POSIX API). Most Linux distributions are based on glibc. OTOH, Alpine Linux is based on the musl libc library, which is a minimal implementation and strictly POSIX compliant. Executables built on glibc distributions depend on /lib/x86_64-linux-gnu/libc.so.6, for example, which is not available on Alpine (unless, they are statically linked).

Except for this dependency, it's important to note that while musl attempts to maintain glibc compatibility to some extent, it is far from being fully compatible, and complex software that's built against glibc won't work with musl-libc, so simply symlinking /lib/ld-musl-x86_64.so.1 to the glibc path isn't likely going to work.

Generally, there are several ways for running glibc binaries on Alpine:

  1. Install the libc6 compatibility package: apk add libc6-compat.
    This package provides a light weight glibc compatibility layer. For simple applications, this may be sufficient.

  2. Install proper glibc on Alpine, for providing all glibc methods and functionalities. There are glibc builds available for Alpine, which should be installed in the following procedure (example):

# Source: https://github.com/anapsix/docker-alpine-java

ENV GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc
ENV GLIBC_VERSION=2.30-r0

RUN set -ex && 
    apk --update add libstdc++ curl ca-certificates && 
    for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; 
        do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && 
    apk add --allow-untrusted /tmp/*.apk && 
    rm -v /tmp/*.apk && 
    /usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
  1. Use statically linked executables. Static executables don't carry dynamic dependencies and could run on any Linux.

  2. Alternatively, the software may be built from source on Alpine.

For LibreDWG, let's first verify the issue:

/usr/local/bin # ./dwg2dxf
/bin/sh: ./dwg2dxf: not found
/usr/local/bin
/usr/local/bin # ldd ./dwg2dxf
    /lib64/ld-linux-x86-64.so.2 (0x7fd375538000)
    libredwg.so.0 => /usr/local/lib/libredwg.so.0 (0x7fd3744db000)
    libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fd375538000)
    libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fd375538000)
Error relocating /usr/local/lib/libredwg.so.0: __strcat_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __snprintf_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __memcpy_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __stpcpy_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __strcpy_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __printf_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __fprintf_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __strncat_chk: symbol not found
Error relocating /usr/local/lib/libredwg.so.0: __sprintf_chk: symbol not found
Error relocating ./dwg2dxf: __snprintf_chk: symbol not found
Error relocating ./dwg2dxf: __printf_chk: symbol not found
Error relocating ./dwg2dxf: __fprintf_chk: symbol not found

You can see that dwg2dxf depends on several glibc symbols. Now, let's follow option 2 for installing glibc:

/usr/src/app # cd /usr/local/bin
/usr/local/bin # ls
dwg2SVG     dwg2dxf     dwgadd      dwgbmp      dwgfilter   dwggrep     dwglayers   dwgread     dwgrewrite  dwgwrite    dxf2dwg     dxfwrite
/usr/local/bin # ./dwg2dxf
/bin/sh: ./dwg2dxf: not found
/usr/local/bin # export GLIBC_REPO=https://github.com/sgerrand/alpine-pkg-glibc && 
> export GLIBC_VERSION=2.30-r0 && 
> apk --update add libstdc++ curl ca-certificates && 
> for pkg in glibc-${GLIBC_VERSION} glibc-bin-${GLIBC_VERSION}; 
>    do curl -sSL ${GLIBC_REPO}/releases/download/${GLIBC_VERSION}/${pkg}.apk -o /tmp/${pkg}.apk; done && 
> apk add --allow-untrusted /tmp/*.apk && 
> rm -v /tmp/*.apk && 
> /usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
(1/1) Installing curl (7.74.0-r1)
Executing busybox-1.32.1-r3.trigger
OK: 629 MiB in 126 packages
(1/2) Installing glibc (2.30-r0)
(2/2) Installing glibc-bin (2.30-r0)
Executing glibc-bin-2.30-r0.trigger
/usr/glibc-compat/sbin/ldconfig: /usr/local/lib/libredwg.so.0 is not a symbolic link
/usr/glibc-compat/sbin/ldconfig: /usr/glibc-compat/lib/ld-linux-x86-64.so.2 is not a symbolic link
OK: 640 MiB in 128 packages
removed '/tmp/glibc-2.30-r0.apk'
removed '/tmp/glibc-bin-2.30-r0.apk'
/usr/glibc-compat/sbin/ldconfig: /usr/glibc-compat/lib/ld-linux-x86-64.so.2 is not a symbolic link

/usr/glibc-compat/sbin/ldconfig: /usr/local/lib/libredwg.so.0 is not a symbolic link

Voila:

/usr/local/bin # ./dwg2dxf

Usage: dwg2dxf [-v[N]] [--as rNNNN] [-m|--minimal] [-b|--binary] DWGFILES...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...