前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于 Alpine 的 Docker 镜像编译的程序无法在云函数环境运行

基于 Alpine 的 Docker 镜像编译的程序无法在云函数环境运行

原创
作者头像
ritchiechen
修改2019-11-11 11:25:47
5.7K0
修改2019-11-11 11:25:47
举报
文章被收录于专栏:Serverless+

最近有一个用户反馈, 他使用 golang:1.13.1-alpine3.10 这个镜像来编译的可执行程序无法在云函数的环境运行, 报错信息如下:

代码语言:txt
复制
fork/exec /var/user/main: no such file or directory

macOS 下编译则没有这个问题

问题定位

还未来得及定位问题, 用户便反馈说换了一个镜像就没问题了, 于是没能获得更多信息

过了几天, 有一个同事在群里贴出了 Go 程序链接出错的信息, 看起来也是在 Alpine Linux 下编译的, 有人回复道 Alpine Linux 使用的不是 glibc

啊哈, 终于有线索了, 写代码验证一下

代码语言:txt
复制
package main

import "fmt"

func main() {
	fmt.Println("hello world")
}

CentOS 上编译后, 使用 ldd 查看一下程序依赖哪些 .so(也可以使用 readelf -d)

代码语言:txt
复制
$ ldd main
        not a dynamic executable

程序太简单了, 没有依赖动态库

搜索了一下, 发现 Go 的仓库有一个 issue #33019, 和我们的问题很类似

代码语言:txt
复制
package main

import (
	"net"
	"fmt"
	"os"
)

func main() {
	ips, err := net.LookupIP("localhost")
	if err != nil {
		fmt.Fprintf(os.Stderr, "Could not get IPs: %v\n", err)
		os.Exit(1)
	}
	for _, ip := range ips {
		fmt.Printf("localhost. IN A %s\n", ip.String())
	}
}

编译这段代码, 再次使用 ldd 查看一下程序依赖哪些 .so

代码语言:txt
复制
$ ldd main
        linux-vdso.so.1 =>  (0x00007ffca89c9000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6c4b4bd000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f6c4b0f9000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f6c4aef5000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f6c4b6d9000)

终于和 glibc 扯上关系了

使用 golang:1.13.1-alpine3.10 这个镜像重新编译一下这段代码, 看看结果有什么不同

代码语言:txt
复制
$ docker run -v $PWD:/go/src/test -w /go/src/test golang:1.13.1-alpine3.10 go build -o main-alpine
$ ldd main-alpine
        linux-vdso.so.1 =>  (0x00007ffe0055e000)
        libc.musl-x86_64.so.1 => not found
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f2512754000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2512390000)
        /lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f2512958000)

可以看到, 缺失了 libc.musl-x86_64.so.1, 运行一下程序

代码语言:txt
复制
$ ./main-alpine
-bash: ./main-alpine: /lib/ld-musl-x86_64.so.1: bad ELF interpreter: No such file or directory

No such file or directory 正是本文一开始提到的出错信息

(完整的出错信息可通过使用 Go 的 os/exec 包启动 main-alpine 获得)

解决方案

问题的原因在于云函数的运行环境(CentOS)提供的是 glibc, 而 Alpine Linux 却是 musl libc. 因而使用 golang:1.13.1-alpine3.10 这个镜像编译出来的程序如果依赖于 musl libc, 则会在程序加载的时候找不到所需的动态库

解决问题的方法很简单, 只需将镜像换成 golang:<version> 的版本(如golang:1.12)即可

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题定位
  • 解决方案
相关产品与服务
云函数
云函数(Serverless Cloud Function,SCF)是腾讯云为企业和开发者们提供的无服务器执行环境,帮助您在无需购买和管理服务器的情况下运行代码。您只需使用平台支持的语言编写核心代码并设置代码运行的条件,即可在腾讯云基础设施上弹性、安全地运行代码。云函数是实时文件处理和数据处理等场景下理想的计算平台。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档