Docker scratch 无法正常运行golang二进制程序的问题 (2)

是我的二进制程序没有编译成功吗?其实不是。从构建日志中,我们可以清楚的看到,程序其实是编译成功的,也成功的COPY到了最终的运行镜像中,然后启动的时候就是出错了。所以首先我们就排除了代码和Dockerfile的问题。

 

此处我曾经疑惑了很久,因为容器运行报上述错误是让人非常摸不着头脑的。我尝试用搜索引擎进行搜索,确实搜到了结果:

 

docker启动报错:standard_init_linux.go:211: exec user process caused "no such file or directory"

     如题所示,根据自己构建的镜像启动docker容器,直接退出,查看容器日志报错信息,没有任何别的信息。网上搜索这个问题,发现很多人都遇到过,解决办法也各不相同,最后发现一篇文章。受到启发,我的项目是java项目,通过ENTRYPOINT命令启动脚本docker-entrypoint.sh来构建一个在后台运行的服务。而我的docker-entrypoint.sh是在windows下编辑的,自然fileformat是dos,这里需要修改为unix,修改办法也很简答,无需再在linux下操作,我们一般机器上安装了git工具,自带了git bash命令行工具,进入git bash,找到该文件docker-entrypoint.sh,然后使用vi编辑,修改fileformat=unix,如下所示。

————————————————

原文链接:https://blog.csdn.net/feinifi/java/article/details/102910715

 

然而这个问题却与我们无关,因为我们根本没有用到entrypoint的功能。

 

现在我们回到本节开始的地方:scratch是一个空镜像,意味这Docker内部不存在任何环境和依赖库。这就意味着即使是最常见的依赖,在scratch中也是不存在的,那么我们检查一下helloworld和httpserver两个二进制文件的依赖,看看是不是能看出一些端倪。

 

$ go build http_server.go

$ ldd http_server

        linux-vdso.so.1 (0x00007fffc4eaf000)

        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fecea090000)

        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fece9c90000)

        /lib64/ld-linux-x86-64.so.2 (0x00007fecea400000)

 

真相大白,即使golang宣传了二进制文件不需要依赖任何外部文件,但是即使是程序运行最基础的libc,scratch也是不包含的。这直接导致了编译完成的httpserver无法运行,但是容器的报错却是找不到文件,报错让人摸不着头脑,希望这篇文章能提供一些小小的帮助。

 

理论上来说,如果在scratch中添加需要的动态库,最终是可以让程序正常运行的,但这违背了简化开发流程的原则,同时会在代码中增加不必要的负担。因此,常见的golang程序使用alpine作为最终的运行环境的基础镜像已经是一个非常折衷和合适的方案,不建议再去scratch上折腾。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzswx.html