在Docker映像中使用CGO进行Golang交叉编译

q35jwt9p  于 2023-01-28  发布在  Go
关注(0)|答案(1)|浏览(401)
    • bounty将在4天后过期**。回答此问题可获得+100声望奖励。ravi kumar希望引起更多人关注此问题。
    • 要求**:应用程序必须作为Docker映像进行容器化,并且需要支持arm64amd64体系结构。
    • 代码库**:这是一个golang应用程序,需要使用git2go库,并且必须有CGO_ENABLED=1来构建项目。
    • 主机**:我正在使用arm64 m1 mac和docker桌面来构建应用程序,但在我们的amd64 jenkins ci构建系统上结果相似。
    • 停靠文件**:
FROM golang:1.17.6-alpine3.15 as builder

WORKDIR /workspace
COPY go.mod go.mod
COPY go.sum go.sum

RUN apk add --no-cache libgit2 libgit2-dev git gcc g++ pkgconfig

RUN go mod download

COPY main.go main.go

ARG TARGETARCH TARGETOS

RUN CGO_ENABLED=1 GO111MODULE=on GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -tags static,system_libgit2 -a -o gitoperations main.go

FROM alpine:3.15 as runner

WORKDIR /
COPY --from=builder /workspace/gitoperations .
ENTRYPOINT ["/gitoperations"]
    • 这就是我构建映像的方式**:
docker buildx create --name gitops --use
docker buildx build --platform=linux/amd64,linux/arm64 --pull .

此设置工作正常,但在构建不同的拱门时,构建花费的时间太长。此特定构建步骤之间的时间差为:RUN CGO_ENABLED=1 GO111MODULE=on GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -tags static,system_libgit2 -a -o gitoperations main.go在构建不同的拱时总是长10倍:
示例:
1.在arm64 M1 mac(不带rossetta)上:构建arm64可执行文件需要约30秒,构建amd64需要约300秒。
1.在我们的amd64 Jenkins CI系统上:构建arm64可执行文件的时间比构建amd64可执行文件的时间长10倍。
通过查看docker buildx build命令输出可以看到此构建时间。
我相信(当然我也可能是错的)这是因为docker在构建一个cpu架构时使用了qemu仿真,而这个架构和主机的cpu架构是不一样的,所以我想利用golang的交叉编译功能来加快构建时间。

    • 我尝试过的**:我想在这个dockerfile中为arm和amd arch使用一个builder stage,尝试使用以下语法:

FROM --platform=$BUILDPLATFORM golang:1.17.6-alpine3.15 as builder。但在对dockerfile进行此更改后使用相同的docker构建命令会出现构建错误,这是我在arm64 M1 mac上运行时得到的结果:

> [linux/arm64->amd64 builder 9/9] RUN CGO_ENABLED=1 GO111MODULE=on GOOS=linux GOARCH=amd64 go build -tags static,system_libgit2 -a -o gitoperations main.go:
#0 1.219 # runtime/cgo
#0 1.219 gcc: error: unrecognized command-line option '-m64'

在阅读了golang CGO文档后,我认为发生此错误的原因是go没有选择能够为两种架构构建的正确c编译器,我需要设置CC env变量以指示go使用哪个c编译器。

    • 问题**:我假设是qemu导致了构建时间的差异,并且可以通过使用golang的本机交叉编译功能来减少这种差异,对吗?

我如何使用Docker桌面从任何主机上为amd64和arm64编译go build,因为我没有任何使用C代码和gcc的经验,并且如果我需要支持linux/amd64linux/arm64,我不确定应该为go build命令中的CC标志设置什么值?

bvjxkvbb

bvjxkvbb1#

顺便说一句,我想分享一下我的经验,我也尝试过用GitHub Actions构建一个Go应用程序Docker映像,Go build是在Docker内部运行的,虽然应用程序不是很大,但我觉得这是一个相当长的过程。然后我尝试在Docker外部构建二进制文件,这个过程要快得多,特别是如果我们存储了之前构建过程中该高速缓存。

相关问题