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/
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:
# apk add gcompat
apk add libc6-compat
Both packages provide a light weight glibc compatibility layer which may be suitable for running simple glibc applications.
libc6-compat
implements glibc compatibility APIs and provides symlinks to glibc shared libraries such as libm.so
, libpthread.so
and libcrypt.so
. The gcompat
package is based on Adelie Linux gcompat project and does the same but provides a single library libgcompat.so
. Both libraries install loader stubs. Depdending on the application, one of them may work while the other won't, so it's good to try both.
# 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
Use statically linked executables. Static executables don't carry dynamic dependencies and could run on any Linux.
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...
Try apk add gcompat
(https://pkgs.alpinelinux.org/package/edge/community/x86/gcompat).
gcompat
provides both /lib64/ld-linux-x86-64.so.2
and /lib/ld-linux-x86-64.so.2
(https://pkgs.alpinelinux.org/contents?file=ld-linux-x86-64.so.2).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With