【问题标题】:Docker scratch image not showing up as arm64Docker 暂存图像未显示为 arm64
【发布时间】:2021-05-28 08:25:51
【问题描述】:

我正在为多种架构(amd64 和 arm64 - 都在 Linux 上)构建 Docker 映像。我正在使用多阶段构建 - 这意味着使用 go-alpine 映像作为构建器(将我的 Go 源代码编译为可执行文件),然后将可执行文件复制到较小的辅助映像。

最初,我将编译后的程序复制到 Alpine 映像中,但我决定切换到临时映像(出于安全考虑) - 这涉及更改我的构建命令,以便生成的可执行文件是静态链接的。我的 Dockerfile 现在是:

FROM golang:1.16 AS builder
WORKDIR /go/src/
RUN go get -d -v ./...
COPY . .
RUN env ${opts} go build -a -installsuffix cgo -o app .

FROM scratch
WORKDIR /root/
COPY --from=builder /go/src/app .
CMD ["./app"]

当我为 amd64 构建时,我运行 docker build --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=amd64" -t myuser/example:amd64 . - 如果我检查这张图片,它会按预期显示"Architecture": "amd64"

当我为 arm64 构建时,我运行 docker build --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=arm64" -t myuser/example:arm64 . - 如果我检查这张图片,它会显示 "Architecture": "amd64" - 这不是我想要的。

如果我通过运行CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build在本地编译Go代码,然后在编译器输出上运行file,则显示编译后的输出是arm64。因此,我认为问题是 Docker 拉取 amd64 基础映像的结果(因为我的 PC 是 x86),但我不知道如何解决这个问题。

【问题讨论】:

    标签: linux docker go arm


    【解决方案1】:

    您共享的 sn-ps 正在交叉编译您的 Go 二进制文件,但正如您所指出的,仍在使用 amd64 基础映像。为此,您需要为多个平台构建一个 docker 容器:

    https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/

    这个例子是这样的:

    docker buildx build \
    --platform linux/arm64/v8,linux/amd64 \ 
    --tag your-username/multiarch-example:buildx-latest .
    

    使用 docker 平台路由,您不应该需要使用 go-multiarch 构建,因为 go 工具应该推断其构建的平台。

    作为替代方案,您可以在主机上交叉编译二进制文件,然后为每个平台创建一个 docker 镜像,该镜像基于该架构的暂存镜像,然后将您的可执行文件复制进去。

    【讨论】:

      【解决方案2】:

      因为你站在 AMD 机器上,docker 会默认拉取 AMD golang 镜像来构建你的项目。 有几种方法可以解决它,但这种情况我建议使用--platform=$BUILDPLATFORM

      https://docs.docker.com/buildx/working-with-buildx/

      所以,你的 Dockerfile 看起来像:

      FROM --platform=$BUILDPLATFORM golang:1.16 AS builder
      ARG BUILDPLATFORM
      WORKDIR /go/src/
      RUN go get -d -v ./...
      COPY . .
      RUN env ${opts} go build -a -installsuffix cgo -o app .
      
      FROM --platform=$BUILDPLATFORM scratch
      WORKDIR /root/
      COPY --from=builder /go/src/app .
      CMD ["./app"]
      

      以及你本地的构建命令:

      docker build --build-arg BUILDPLATFORM=linux/arm64 --build-arg opts="CGO_ENABLED=0 GOOS=linux GOARCH=arm64" -t myuser/example:arm64 .
      

      但如果您使用 Github Action 或 CircleCI 构建 Golang 映像,请查看下面的这些博客文章

      带有 Github Action 的 Golang 多架构图像 https://namiops.medium.com/golang-multi-arch-docker-image-with-github-action-b59a62c8d2bd

      带有 CircleCI 的 Golang 手臂图像 https://namiops.medium.com/golang-arm64-docker-image-with-circleci-arm-machine-8bebf2151b92

      【讨论】:

      • 不应该从头开始使用 $TARGETPLATFORM 吗?
      猜你喜欢
      • 2020-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 2020-08-18
      • 2022-08-04
      • 1970-01-01
      • 2018-03-05
      相关资源
      最近更新 更多