最近在ubantu 上进行了 iris项目的alpine 版本打包,过程遇到了一些问题,记录一下。
golang版本 :1.18
系统:ubantu
代码结构
Dockfile内容
FROM alpine:latest
MAINTAINER Si Wei<3320376695@qq.com>
ENV VERSION 1.1
ENV GO111MODULE=on
ENV CGO_ENABLED 0
WORKDIR /app
RUN mkdir -p /usr/share/zoneinfo/Asia/
COPY deploy/Shanghai /usr/share/zoneinfo/Asia/Shanghai
COPY qycloud-irisOps /app/qycloud-irisOps
COPY config /app/config
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
ENV LANG C.UTF-8
EXPOSE 8080
ENTRYPOINT ["./qycloud-irisOps"]
错误解决过程
二进制包 qycloud-irisOps 是通过:go build -o qycloud-irisOps
生成的
为啥我的go项目 build打包docker后报这个错误呢
docker: Error response from daemon: failed to create shim: OCI runtime create failed: runc create failed: unable to start container process: exec: “qycloud-irisOps”: executable file not found in $PATH: unknown.
一开始我以为是 文件 ,也就是 ENTRYPOINT [“./qycloud-irisOps”] 这里的问题,在求助同事和朋友之后,很多人第一反应也都是我这里写错了。
根据讨论,我进去容器 去验证了,其实是有这个目录和文件的。 docker run -it --entrypoint "" 镜像名 /bin/sh
那么问题就不是 entrypoint 和 copy 的问题。 排除dockerfile问题。
问题所在
其实这里not found不是说找不到这个程序,而是找不到需要的动态连接库,
go语言是静态编洋型的语言,即使这个程序非常简单,但是它还是依颜了动态链接库,这个动态链接库是系统内置的,而我编译用的系统是ubantu,要在alipline上运行,在ubuntu上用的是glibc.alpine为了追求轻量,选择了musl libc,因此我的程序无法下常动态链接
所以编译的时候禁用外部函数,静态编译。
综上所述,编译时添加参数CGO_ENABLED=0,关闭CGO就可以了:
# 禁用CGO
CGO_ENABLED=0 go build -o qycloud-irisOps
#
docker build -t irisops_docker:v1.0 .
docker run -itd --name=irisGo irisops_docker:v1.0
新的问题
在禁用CGO编译之后,确实可以正常起 docker 启动 go 服务了,但是又报了 mysql.go 的链接错误,这是因为
connString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&interpolateParams=true&loc=", c.User, c.Password, c.Host, c.Port, c.Database, c.Charset)
connString = connString + "Asia%2FShanghai"
var err error
DB, err = gorm.Open("mysql", connString)
if err != nil {
iris.New().Logger().Error("err is", err)
iris.New().Logger().Error("connString is", connString)
log.Panic(err)
os.Exit(-1)
}
这里面 c.Host 的127.0.0.1 在docker中是找不到的,所以 ,改动这里的配置 为 mysql ,然后在 docker run 的时候 改成下面这样 。
docker run --link mysql:mysql -itd --name=irisGo irisops_docker:v1.0
这样mysql报错的问题就解决了。
总结
CGO_ENABLED=0 go build -o qycloud-irisOps -tags netgo
docker run -itd --name=irisGo irisops_docker:v1.0
docker run --link mysql:mysql -itd --name=irisGo irisops_docker:v1.0