且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-08-22 17:06:34

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

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.

世界上大多数 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 上不可用(除非它们是静态链接的).

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).

除了这个依赖之外,需要注意的是,虽然 musl 尝试在一定程度上保持 glibc 的兼容性,但它远非完全兼容,而且针对 glibc 构建的复杂软件无法与 musl-libc 一起使用,所以简单将 /lib/ld-musl-x86_64.so.1 符号链接到 glibc 路径不太可能起作用.

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.

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

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

  1. 安装libc6兼容包:apk 添加libc6-compat.
    这个包提供了一个轻量级的 glibc 兼容层.对于简单的应用程序,这可能就足够了.

  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.

在 Alpine 上安装适当的 glibc,以提供所有 glibc 方法和功能.有可用于 Alpine 的 glibc 版本,应按以下过程(示例)安装:

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. 使用静态链接的可执行文件.静态可执行文件不携带动态依赖项,可以在任何 Linux 上运行.

  1. Use statically linked executables. Static executables don't carry dynamic dependencies and could run on any Linux.

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

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

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

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

你可以看到 dwg2dxf 依赖于几个 glibc 符号.现在,让我们按照选项 2 安装 glibc:

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

瞧:

/usr/local/bin # ./dwg2dxf

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