解决Golang编译的二进制程序在 docker alpine 中报”not found”无法运行的问题
使用 golang 1.17编译的程序运行时报 "not found", 而文件确认存在
/app # ./main
sh: ./main: not found
这个就要从alpine使用的musl libc说起,而对应的则是gnu libc,这两者有什么区别呢?
gnu libc是标准的libc的库,我们大部分时间编译出来的都是可以使用这个库
而Alpine采用了musl libc和busybox 以减小系统的体积和运行时资源消耗
所以用alpine做base的镜像体积非常的小, 很适合用于CI阶段
musl libc只能说是部分兼容gnu libc,因此也不是所有的go编译出来的二进制都无法使用
这两者详细的区别大家可考虑这些链接:
https://blog.csdn.net/liumiaocn/article/details/89702529
解决办法
解决办法简单来说,就是在Alpine里面安装glibc,让Alpine不再是Alpine
apk add --update curl bash net-tools libc6-compat ca-certificates
Golang dockerfile 最佳实践
FROM golang:1.17 as builder
MAINTAINER yangshuhai<yangshuhai@pdnews.cn>
WORKDIR /cache
# 如果 go.mod 没有变化,就能复用之前镜像缓存,加快编译速度
COPY go.mod .
RUN go env -w GOPROXY=https://goproxy.cn
RUN go mod tidy -compat=1.17
WORKDIR /app
COPY . .
RUN go env -w GOPROXY=https://goproxy.cn
RUN go mod tidy -compat=1.17
RUN GOOS=linux go build -ldflags "-w -s" -o app
# 可选,减少二进制包大小
RUN if [ type upx >/dev/null 2>&1 ]; then upx app; fi
FROM alpine:3.14
MAINTAINER yangshuhai<yangshuhai@pdnews.cn>
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.14/main" > /etc/apk/repositories
RUN echo "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.14/community" >> /etc/apk/repositories
RUN apk add --update curl bash net-tools libc6-compat ca-certificates && rm -rf /var/cache/apk/*
WORKDIR /app
COPY --from=builder /app/app main
ADD config-sample.toml config.toml
RUN chmod +x main
CMD ["/app/main"]