持续构建:Alpine镜像下构建的Go语言应用的运行问题
发布日期:2021-06-30 20:16:22 浏览次数:2 分类:技术文章

本文共 2469 字,大约阅读时间需要 8 分钟。

Go语言虽然是平台无关性的语言,但是构建出来的应用由于是可执行文件,所以注定无法像Java那样“一次编译、处处运行”,因为Java应用程序的二进制字节码下的解释由JVM这一层来实现,所以能够实现一次编译之后随处运行的平台无关性。这篇文章通过Alpine下编译的二进制文件的运行方式来说明在实际使用中需要注意的一个细节。

使用Alpine构建Go应用

Go提供官方镜像用于构建Go语言的应用,官方镜像中也包括Alpine镜像。如何使用Docker镜像构建Go语言应用可参看:

问题现象

参照上述方式在Alpine镜像中构建的Go的可执行文件,如果在其他操作系统之上比如macOS,可能无法执行,比如如下错误示例:

liumiaocn:random liumiao$ sw_versProductName:	Mac OS XProductVersion:	10.15.2BuildVersion:	19C57liumiaocn:random liumiao$liumiaocn:random liumiao$ ls -l random -rwxr-xr-x  1 liumiao  staff  11818840 Jan  2 05:49 randomliumiaocn:random liumiao$ liumiaocn:random liumiao$ ./random -bash: ./random: cannot execute binary fileliumiaocn:random liumiao$

问题原因

原因很简单,如果使用file就可以看到提示信息,因为此应用中使用到了Alpine下的动态链接库musl

liumiaocn:random liumiao$ file random random: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, Go BuildID=hgTtsNIKz6CaFyd1O013/zRrsBwl7ZanojEmS5VjG/lanZ1NVq7_tlUKyh7Umk/Qt-ybeIFl1WKlkEbxAhh, not strippedliumiaocn:random liumiao$

也可以使用如下方式确认此应用所关联的动态链接库

liumiaocn:random liumiao$ docker run -p 8080:8080 -v `pwd`/random:/random -it --rm alpine sh/ # lsbin     etc     lib     mnt     proc    root    sbin    sys     usrdev     home    media   opt     random  run     srv     tmp     var/ # ldd random	/lib/ld-musl-x86_64.so.1 (0x7f5c916a9000)	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f5c916a9000)/ #

对应方法

对应方法有两种,其一就是使用所在平台进行go语言编译,其二是将此应用运行在Alpine容器中,虽然还有其他方式比如使得所在平台支持musl或者使Alpine支持libc就目前的使用状况而言,基本上都是不太适合的,因为由于这种方式支持的不全面,可能只是保证得了一时的正常动作。这里使用在Alpine容器中运行Alpine镜像编译的应用,比如:

liumiaocn:random liumiao$ docker run -p 8080:8080 -d -v `pwd`/random:/random -it --rm alpine /random -listen-address=:8080f72dc7267ae84abccea73e813a8b433af5d6885d6c57d36707cfea4e9f9ca3f8liumiaocn:random liumiao$

通过如下命令可确认到其能够正常动作

liumiaocn:random liumiao$ curl http://localhost:8080/metrics 2>/dev/null |grep -v '# ' |head -n 10go_build_info{checksum="",path="github.com/prometheus/client_golang",version="(devel)"} 1go_gc_duration_seconds{quantile="0"} 0go_gc_duration_seconds{quantile="0.25"} 0go_gc_duration_seconds{quantile="0.5"} 0go_gc_duration_seconds{quantile="0.75"} 0go_gc_duration_seconds{quantile="1"} 0go_gc_duration_seconds_sum 0go_gc_duration_seconds_count 0go_goroutines 10go_info{version="go1.13.5"} 1liumiaocn:random liumiao$

总结

实际上这个问题一般是反向才会出现的问题,之所以需要在Alpine镜像中构建go语言应用,一般的原因并不是Alpine的Go语言构建镜像过大,而是运行时Alpine由于不支持libc会导致出现在Alpine镜像中无法运行。构建出来的go语言应用加上小巧的Alpine镜像使得最终的部署镜像很小才是实际使用中对大家的一个吸引。

转载地址:https://liumiaocn.blog.csdn.net/article/details/103798353 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Prometheus:监控与告警:4:使用Grafana进行可视化显示
下一篇:持续构建:使用Docker镜像方式构建go语言项目

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月21日 16时40分35秒