linux - Docker 暂存图像未显示为 arm64
问题描述
我正在为多种架构(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"
- 这不是我想要的。
如果我通过运行在本地编译Go代码CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build
,然后file
在编译器输出上运行,它显示编译输出是arm64。因此,我认为问题是 Docker 拉取 amd64 基础映像的结果(因为我的 PC 是 x86),但我不知道如何解决这个问题。
解决方案
您共享的片段正在交叉编译您的 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 镜像,该镜像基于该架构的暂存镜像,并将您的可执行文件复制进去。