首页 > 解决方案 > 为什么基于 ARM 的 Go 应用程序的 Dockerfile 从运行时路径中删除“linux_arm”?

问题描述

我正在使用如下的 Dockerfile 在docker build基于 ARM 的 Raspberry Pi 上创建图像。但它在这COPY --from=builder一步失败了,因为它找不到路径“/go/bin/linux_arm/example-experiment”,并且在“builder”阶段结束时的几个调试“ls”命令显示创建的实际路径在那个阶段是“/go/bin/example-experiment(即缺少“linux_arm”目录级别):

FROM golang:latest AS builder

ENV GOPATH $GOPATH:/go/src/example-experiment
ENV GOOS linux
ENV GOARCH arm
ENV GOARM 7

RUN apt-get update && apt-get install git

ADD . /go/src/example-experiment/
WORKDIR /go/src/example-experiment

RUN go get -v ./...

RUN go install
                                                                                                                                                                            
FROM scratch

# Copy the static executable.
COPY --from=builder /go/bin/linux_arm/example-experiment /go/bin/linux_arm/example-experiment

# Run the application's executable binary.
ENTRYPOINT ["/go/bin/linux_arm/example-experiment"]

我尝试替换RUN go installRUN go build但同样的事情发生了。

可能这更多地是关于 Go 而不是 Docker。但是使用相同的 Dockerfile 运行构建的同事发现它完成时没有错误,并且可能他们的基础镜像使用了相同版本的 Go。

实际错误如下:

Step 19/20 : COPY --from=builder /go/bin/linux_arm/example-experiment /go/bin/linux_arm/example-experiment
COPY failed: stat /var/lib/docker/overlay2/36eef7ea57e69d51c9f00dc151fde8c0e7cd38a2ca3e51505c153594f57db5ba/merged/go/bin/linux_arm/example-experiment: no such file or directory

我认为 Go 应该创建一个运行时路径 /go/bin/$GOOS_$GOARCH/... 在这种情况下是 /go/bin/linux_arm/...

标签: dockergodockerfile

解决方案


一直在对此进行更多挖掘..

显然,go install工作方式是本地二进制文件转到 $GOPATH/bin,交叉编译的二进制文件转到 $GOPATH/bin/${GOOS}_${GOARCH]

因此,如果映像是在 Windows 上构建的(就像我的同事所做的那样),那么 ARM 构建被视为交叉编译,并且 bin 目录设置为 /go/bin/linux_arm,这是后面的COPY --from=builder命令所期望的,所以一切正常。

但是当(和我一样)在 Raspberry Pi 上完成相同的构建时,二进制路径被假定为 /go/bin,并且该COPY命令找不到它期望的目录。

我已经确认有效的解决方案是定义二进制路径,以便在任何一种情况下都相同,方法是将 GOBIN 环境变量设置为:

ENV GOBIN /go/bin/${GOOS}_${GOOARCH}

所以这一次我已经回答了我自己的问题。

(我还在问题中添加了“go”标签,因为这并不是真正的 Docker 问题。但我留下了“docker”和“dockerfile”标签,以防其他构建基于 go 的 Docker 映像的人遇到同样的问题.)


推荐阅读