Docker多阶段构建scratch运行Go程序报文件不存在问题咨询
问题根因
报错和重复的FROM scratch配置无直接关联,核心原因有两个:
- 构建阶段使用的
golang:1.18-alpine镜像默认开启CGO,编译出的Go二进制为动态链接版本,依赖系统libc库才能运行。而scratch是完全空白的镜像,不存在任何系统依赖库,系统加载程序时找不到依赖的链接文件,就会抛出exec /query_check_span: no such file or directory错误——这个报错不是指二进制文件没复制到镜像里,是二进制运行需要的依赖文件不存在。替换成alpine镜像后能正常运行,就是因为alpine内置了musl libc,满足动态链接的运行要求。 - 原Dockerfile存在冗余无效配置:连续写了两次
FROM scratch和WORKDIR /,第二次FROM声明会直接覆盖前一个scratch阶段的所有配置,属于无意义的重复写法。另外构建阶段执行go build .没有指定输出二进制名,默认生成的二进制名和工作目录名一致,复制阶段写死app/query_check_span路径很容易出现路径匹配错误。
修正方案
要在scratch镜像中运行Go程序,必须编译纯静态的Go二进制文件,不需要依赖任何外部系统库,修正后的Dockerfile如下:
# syntax=docker/dockerfile:1 ## ## 构建阶段 ## FROM golang:1.18-alpine AS build ENV GO111MODULE=on WORKDIR /app # 优先拷贝依赖清单,利用Docker缓存加速后续构建 COPY go.mod go.sum ./ RUN go mod download # 拷贝全量项目代码 COPY . . # 关闭CGO编译纯静态二进制,明确指定输出路径,避免路径匹配错误 RUN CGO_ENABLED=0 GOOS=linux go build -o /query_check_span . ## ## 运行阶段 ## FROM scratch # 可选配置:如果程序需要调用HTTPS接口,从构建阶段拷贝CA根证书,否则会出现证书校验失败 # COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ # 直接拷贝编译好的静态二进制到镜像根目录 COPY --from=build /query_check_span /query_check_span EXPOSE 8080 ENTRYPOINT [ "/query_check_span" ]
构建运行验证
直接使用原有构建命令即可完成镜像构建:docker build -t qcheck:multi -f .\Dockerfile.multi .
构建完成后执行docker run -p 8080:8080 qcheck:multi,无报错即说明服务正常启动。
内容的提问来源于stack exchange,提问作者Xbel
相关产品推荐
相关产品推荐

