即使在 PATH 中也找不到 Docker Alpine 可执行二进制文件



我有一个高山跑步容器,其中包含一些二进制文件usr/local/bin

当我lsusr/local/bin的内容时,我得到了这个输出:

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

这是我所期望的。 但是,如果我通过调用它来执行这些二进制文件之一,我会从 shell 收到一个not found错误:

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

我测试了我的$PATH似乎是正确的:

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

如何使这些二进制文件可调用或"可找到"?我在我的 Dockerfile 构建中错过了什么吗? 我想阿尔卑斯山的ldconfig命令出了问题,但我不确定。

编辑

正如这里的一个答案所建议的那样,我执行了file命令,这是输出:

/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

这些二进制文件来自 LibreDWG 官方存储库以及我的 Dockerfile 的第一部分。这是完整的 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/

在 Alpine Linux 上,not found错误是动态链路故障的典型症状。这确实是musl的ldd链接器的一个相当令人困惑的错误。

世界上大多数Linux软件都与glibc,GNU libc库(libc提供标准的C库和POSIX API)相关联。大多数Linux发行版都基于glibc。OTOH,Alpine Linux基于musl libc库,这是一个最小的实现,并且严格遵守POSIX标准。例如,建立在glibc发行版上的可执行文件依赖于/lib/x86_64-linux-gnu/libc.so.6,这在Alpine上不可用(除非它们是静态链接的)。

除了这种依赖关系之外,重要的是要注意,虽然 musl 试图在某种程度上保持 glibc 兼容性,但它远非完全兼容,并且针对 glibc 构建的复杂软件不适用于 musl-libc,因此简单地将/lib/ld-musl-x86_64.so.1符号链接到 glibc 路径不太可能起作用。

通常,有几种方法可以在 Alpine 上运行 glibc 二进制文件:

  1. 安装一个glibc兼容包,libc6兼容或gcompat:
# apk add gcompat
apk add libc6-compat

这两个软件包都提供了一个轻量级的glibc兼容层,可能适合运行简单的glibc应用程序。libc6-compat实现了 glibc 兼容性 API,并提供指向 glibc 共享库(如libm.solibpthread.solibcrypt.so)的符号链接。gcompat包基于 Adelie Linux gcompat 项目,并执行相同的操作,但提供了一个库libgcompat.so。两个库都安装加载程序存根。在应用程序上,其中一个可能有效,而另一个则不起作用,因此最好同时尝试两者。

  1. 在Alpine上安装适当的glibc,以提供所有glibc方法和功能。有可用于 Alpine 的 glibc 构建,应按以下过程(示例)进行安装:
# 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. 使用静态链接的可执行文件。静态可执行文件不携带动态依赖项,可以在任何 Linux 上运行。

  2. 或者,该软件可以从 Alpine 上的源代码构建。

对于 LibreDWG,让我们首先验证问题:

/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

您可以看到dwg2dxf取决于几个 glibc 符号。 现在,让我们按照选项 2 安装 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

瞧:

/usr/local/bin # ./dwg2dxf
Usage: dwg2dxf [-v[N]] [--as rNNNN] [-m|--minimal] [-b|--binary] DWGFILES...

尝试apk add gcompat(https://pkgs.alpinelinux.org/package/edge/community/x86/gcompat)。

gcompat提供/lib64/ld-linux-x86-64.so.2/lib/ld-linux-x86-64.so.2(https://pkgs.alpinelinux.org/contents?file=ld-linux-x86-64.so.2)。

编辑 :

有关完整的解决方案,请参阅@valiano的响应。

这只是我在阅读@valiano响应之前找到的解决方法

解决方法

我通过切换到另一个基本映像(基于 Ubuntu)找到了解决方法 这是新的工作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:ubuntu-small-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 
&& apt-get update && apt-get install -y --no-install-recommends build-essential 
libc6 python3-pip libffi-dev musl-dev gcc python3-dev postgresql-server-dev-all
&& 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
# copy project
COPY . /usr/src/app/

基本上我只是改变了

FROM osgeo/gdal:alpine-normal-latest

FROM osgeo/gdal:ubuntu-small-latest

我也更新了依赖项安装(从apk add高山PM切换到apt-get)

这对我来说不是一个理想的解决方案,因为使用基于阿尔卑斯山的图像会生成更轻量级的容器,但它正在工作,所以我将其作为可能的解决方案发布。

@valiano响应是最佳解决方案。如果您关心 lightweigth 图像,请参考它。

我是这样解决的:

rm /usr/glibc-compat/lib/ld-linux-x86-64.so.2
ln -s /usr/glibc-compat/sbin/ldconfig /usr/glibc-compat/lib/ld-linux-x86-64.so.2

编辑:解释:/usr/glibc-compat/sbin/ldconfig/usr/glibc-compat/lib/ld-linux-x86-64.so.2都是 docker 容器中的普通文件,所以我尝试了其中一个。

首先,我删除了/usr/glibc-compat/sbin/ldconfig并使其成为符号链接。但是我有一个错误,不记得是哪个了。 接下来,我尝试删除ld-linux-x86-64.so.2并使其成为符号链接。这奏效了。

它可能不是您可以在相关系统上使用的二进制格式。检查体系结构和文件格式(例如,使用file命令)。

编辑:/lib64/ld-linux-x86-64.so.2存在吗?你能运行它吗?

进一步编辑: 这里的一般思想是,可以将动态链接的二进制文件视为带有解释器的脚本。有关更多详细信息,请参阅此 LWN 文章以了解此处可能发生的事情。如果您的二进制文件适用于错误的平台,您将需要新的二进制文件,或者您需要在正确的平台上运行它们。

您可以检查的另一件事是,此二进制文件的file输出是否与正常工作的二进制文件的file输出不同(例如/bin/ls)。

现在我们可以使用docker compose来替换docker-compose

对于 Alpine Linux,请通过以下方式安装

apk add docker-cli-compose

如果您仍然喜欢docker-compose,则可以使用 a+x 在/usr/local/bin/docker-compose 下保存一个文件:

#!/bin/sh
docker compose $@

然后你仍然可以运行使用docker-compose的旧脚本。

最新更新