问题描述:
在docker中运行go程序报错:not found
/app # ls
service-inv
/app # ./service-inv
/bin/sh: ./service-inv: not found
检查原因:
程序运行的时候找不到动态链接的目标文件
/app # ls
service-inv
/app # ldd service-inv
/lib64/ld-linux-x86-64.so.2 (0x7fa611092000)
Error loading shared library libresolv.so.2: No such file or directory (needed by service-inv)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fa611092000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fa611092000)
Error relocating service-inv: __res_search: symbol not found
动态连接:
我们都知道,程序编写完毕后需要编译、链接才能运行。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,最终形成可执行代码的过程。按理来讲,我们的代码变成可执行的程序的时候,需要调用的代码都已经被链接好了,但是这并不完全准确,因为在此时完成的只是静态链接。 所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。静态链接的问题很明显,它会造成空间的浪费和软件更新的困难。举例来说,当有好几个程序调用了相同的系统函数时,每个程序都把这个函数加载到内存里,重复占用了很多空间,造成了资源的浪费。 动态链接解决了这一问题,其基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。
问题描述:
The GNU C Library(glibc) 是当代绝大多数 Linux 发行版内置的 C 标准库实现,而 musl libc 则是一个速度快、轻量化的,严格遵循 POSIX 定义的 C 标准库实现。虽然后者试图保持与 glibc 的兼容性,但两者间的差距始终不小,在使用时依旧会有兼容性问题。 Alpine 为了简单轻量,没有使用大多数 Linux 发行版使用的 glibc 而选择了 musl libc。因为程序是在Linux系统上编译的,基于 glibc,而 Docker 容器选择了 Alpine 镜像,使用的是 musl libc,所以无法正常动态链接,也就无法运行。
解决方案:
- docker镜像不用Alpine,选择和编译环境一致的发行版;或者在Alpine环境下编译运行
- 编译时指定参数采用静态链接编译
# 通过-tags netgo指定静态链接
go build -tags netgo -o main .
- 编译时指定环境变量禁用CGO
# 禁用CGO
ENV CGO_ENABLED=0
go build -o main .
- 在Dockerfile构建配置中加入lib64的软连接
# 在Dockerfile编写加入lib64的软连接的操作
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
- 在Dockerfile构建配置中加入安装glibc的操作
# 在Dockerfile编写安装glibc的操作
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
亲测选择其中任意一种解决方案可以解决当前程序无法执行的问题
参考文献:
● https://naiv.fun/Ops/binary-not-found-in-Alpine.html