最近在搞系统迁移, 将golang打包环境也准备放到容器内, 之前是在jenkins服务器上,需要迁移, 考虑到CI速度和体验,准备用alpine作为build image。 然后 就遇到了一些。。问题
下载golang和解压过程这里不做赘述,然后:
使用go version
检查go版本报错:
/ # go version
sh: go: not found
使用在go安装目录使用ldd
命令查看所依赖的共享库列表
/usr/local/go/bin # ldd go
/lib64/ld-linux-x86-64.so.2 (0x7f150b281000)
Error loading shared library libresolv.so.2: No such file or directory (needed by go)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f150b281000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f150b281000)
可以看到详细的错误为“Error loading shared library libresolv.so.2: No such file or directory (needed by go)”,这个错误是因为您在Alpine系统上安装Go 1.21时,Go编译器试图加载一个不存在的库libresolv.so.2,这个库是系统C库的一部分。Alpine系统使用了一个不同的C库(musl libc),它更小,但是也可能会遇到一些兼容性问题。有两种可能的解决方法:
- 可以尝试在Alpine系统上安装一个虚拟的libresolv.so.2库,或者将libc.so.6链接到这个名字,这样Go编译器就不会报错了。
- 可以尝试切换到一个基于Debian或Ubuntu的系统,它们使用了更标准的GNU libc库
解决
在Alpine系统上,打开一个终端窗口,输入
apk add musl-dev
这样可以安装musl libc的开发包,其中包含了libc.so文件。然后,输入
ln -s /usr/lib/libc.so /usr/lib/libresolv.so.2
这样可以创建一个指向libc.so的符号链接,命名为libresolv.so.2。
然后:
ldconfig
go version
至此应该是解决了。
反转
运行go build的二进制文件系统是centos, 然后运行二进制喜提报错:
/lib/ld-musl-x86_64.so.1: bad ELF interpreter: No such file or directory
到这就比较明确了,go build环境的系统 要与 二进制运行的系统一致。回头将alpine镜像换成centos镜像。虽然慢, 但是能用。
当然 也可以在centos系统内安装这个静态库:
yum install -y musl-libc-static
但是 但是,不要给自己找麻烦, 系统一致就行了。
附录:构建Dockerfile
FROM centosgo:1.21 AS build
ENV TZ "Asia/Shanghai"
ENV PATH=/usr/local/bin/:/usr/local/gcc/bin/:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV CGO_ENABLED=1
ENV CC=/usr/bin/gcc
RUN set -xe \
&& mkdir -p /tmp/builddir/ && cd /tmp/builddir/ \
&& go mod init. \
&& time sh -x /tmp/builddir/build.sh \
&& ls output
FROM centos_base:1
MAINTAINER
ENV TZ "Asia/Shanghai"
COPY --from=build /tmp/builddir/output/ /data0/
add . /tmp/
RUN set -xe \
&& cd /tmp/ && sh -x add.sh \
&& rpm --rebuilddb && yum install -y psmisc \
&& yum clean all \
&& rm -rf /tmp/*
CMD /bin/sh -x start.sh
EXPOSE 80