如何为Docker构建设置arm64架构?

30
我有一个在amd64上运行的Dockerfile,但希望在arm64上运行。由于go构建工具需要以GOARCH=arm64为参数,因此我不需要任何其他交叉编译工具来生成二进制文件。
# Run the build
FROM mojlighetsministeriet/go-polymer-faster-build
ENV WORKDIR /go/src/github.com/mojlighetsministeriet/email
COPY . $WORKDIR
WORKDIR $WORKDIR
RUN go get -t -v ./...
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build

# Create the final docker image
FROM scratch
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=0 /go/src/github.com/mojlighetsministeriet/email/email /
ENTRYPOINT ["/email"]

问题在于生成的镜像被错误地标记为 Architecture amd64 而不是 arm64。我该如何在 docker build 中传递参数以将 Architecture 设置为 arm64?
$ docker image inspect mojlighetsministeriet/email-arm64                            
[
    {
        "Id": "sha256:33bcd7da8631c7a0829d61cc53479a26ab7f31fab1cb039105de415ddc6178f3",
        "RepoTags": [
            "mojlighetsministeriet/email-arm64:latest"
        ],
        "RepoDigests": [
            "mojlighetsministeriet/email-arm64@sha256:ab3f05d5597c3a304953b5c14f795179aa75bdfd458af3dc3cfb8b8d8eb87bc3"
        ],
        "Parent": "sha256:e5888262d93ea0946b5fd8146cf1c19ec3a7bac4d36eb51848ef0aefa75cf8e7",
        "Comment": "",
        "Created": "2017-12-05T18:36:36.273648787Z",
        "Container": "7a226edb3b52aaeeefec9e0fb4dd1da50d84992fb6cc374aeda9d82eec1bb2c8",
        "ContainerConfig": {
            "Hostname": "7a226edb3b52",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "ENTRYPOINT [\"/email\"]"
            ],
            "Image": "sha256:e5888262d93ea0946b5fd8146cf1c19ec3a7bac4d36eb51848ef0aefa75cf8e7",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/email"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "17.10.0-ce",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": null,
            "Image": "sha256:e5888262d93ea0946b5fd8146cf1c19ec3a7bac4d36eb51848ef0aefa75cf8e7",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/email"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 7861466,
        "VirtualSize": 7861466,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/03cb0162bf922636e4e0ec90123b81565a447c6cd511741103551d2f0e7f09f9/diff",
                "MergedDir": "/var/lib/docker/overlay2/091f74815a0caf457df7e57ade43b41c4dd8551388beca44815a7038501742ee/merged",
                "UpperDir": "/var/lib/docker/overlay2/091f74815a0caf457df7e57ade43b41c4dd8551388beca44815a7038501742ee/diff",
                "WorkDir": "/var/lib/docker/overlay2/091f74815a0caf457df7e57ade43b41c4dd8551388beca44815a7038501742ee/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:66f615d03920919b0fa8bc9fed45515bb95636be1837fdd10a82b2c183e2ad5b",
                "sha256:bd6a01b885eb6e3eec38a3fe3a2899646509633730b210cf6987456fd40b8a1c"
            ]
        },
        "Metadata": {
            "LastTagTime": "2017-12-14T10:24:10.796813522+01:00"
        }
    }
]

这可以帮助您: https://github.com/paritytech/parity-snappy/wiki/Docker-build-for-ARM-ARM64 - Anand
我不确定这怎么能帮到我,但我看到了一个设置用于创建rust arm64/aarch64二进制文件的步骤,这一部分我使用上述Dockerfile没有问题。二进制文件是正确的,在我的arm64机器上启动,但镜像被标记为amd64而不是arm64,这将阻止我在docker swarm环境中安排该镜像。我需要一种改变镜像元数据上Architecture属性的方法,但我似乎找不到这样的方法。 - tirithen
你找到答案了吗?我有一个类似的问题,我在dotnet中构建代码,它是平台无关的设计,因此我不需要任何交叉构建设置来获取适用于arm的工作二进制文件。但是docker限制了我使用构建机器的架构。所以现在我被迫在arm机器上构建arm镜像,这非常慢。 - Vladimir Perevalov
5个回答

35

构建单个Docker镜像: 使用命令行设置环境变量或修改您的 .bashrc 或 .zshenv 文件(在 03/2019 的 v19.03.0 中引入)。

export DOCKER_DEFAULT_PLATFORM=linux/arm64

或者,在 Dockerfile 中,包含以下标记在 FROM 命令中(对于多阶段 Dockerfile 构建,该标记仅在第一阶段需要):

FROM --platform=linux/arm64 python:3.7-alpine

在docker-compose构建的过程中,对于每个服务都需要包含平台信息:linux/arm64。例如:

services:  
  frontend:  
    platform: linux/arm64
    build: frontend  
    ports:
      - 80:80  
    depends_on:
      - backend  
  backend:  
    platform: linux/arm64
    build: backend  

另外一种情况是同样可行的,例如您拥有一个苹果M1芯片并想要将镜像部署到基于Linux或Windows的AMD64环境中。只需将“linux/arm64”替换为“linux/amd64”即可。


30

https://docs.docker.com/desktop/multi-arch/

# Shows builders installed
docker buildx ls

# Use builder that supports platform
docker buildx use default

docker buildx build --platform linux/arm64 -t <image_name>:<image_tag> --push .

3
我能够解决这个问题,虽然不完全符合我的要求,但已经足够接近了。
  1. 拥有安装有docker的amd64 Linux机器

  2. 设置qemu用户静态支持arm https://hub.docker.com/r/multiarch/qemu-user-static/

  3. 在您的docker文件中使用具有arm支持的基础镜像。例如ubuntu

  4. 使用类似以下命令构建您的镜像:

    docker build --platform arm --pull -t your_tag .

此命令将强制docker拉取基础镜像的arm版本,并将arm架构设置为您的结果镜像。但是请注意,如果您使用支持多个架构的标签,则上面的命令将把标签设置为arm版本。因此,要运行本机的amd64版本,您需要再次拉取没有--platform参数的标签。


0

我借助qemu-user在amd64主机上构建和运行arm64镜像。但是,docker inspect这些arm64镜像总是显示"Architecture": "amd64"。我希望它可以显示"Architecture": "arm64"

我尝试了DOCKER_DEFAULT_PLATFORM--platform=linux/arm64,但都无效。我使用的是docker 19.03.13。

最后,我找到了解决方案——首先保存镜像,然后更改其元数据,最后将其加载回来:

set -e

IMAGE_ID=$(docker image inspect --format '{{.ID}}' $1)
IMAGE_ID=${IMAGE_ID#sha256:}

if [ ${#IMAGE_ID} -ne 64 ]; then
  echo "Invalid image sha256 id"
  exit 1
fi

rm -rf ${IMAGE_ID}
mkdir -p ${IMAGE_ID}
echo "IMAGE ${IMAGE_ID}"

echo "> save..."
docker save ${IMAGE_ID} | tar -xC ${IMAGE_ID}

echo "> change arch..."
sed -i 's/"architecture":"amd64"/"architecture":"arm64"/' ${IMAGE_ID}/${IMAGE_ID}.json

echo "> reload..."
tar -cC ${IMAGE_ID} . | docker load

echo "> clean..."
rm -rf ${IMAGE_ID}

echo "Note: you need to tag it manually"

将其保存为changeArch.sh,然后运行 sh changeArch.sh <sha_id>sh changeArch.sh <image:tag>


0

之前的答案都对我没用。我正在为每个架构构建一个静态的Go二进制文件,并将其复制到完全空的FROM scratch容器中。我需要采取以下方法,使用docker manifest annotate命令显式设置构建容器的架构:

docker build -f myproject.Dockerfile --pull -t registry.gitlab.com/myuser/myproject/myproject:manifest-arm64 --build-arg ARCH=arm64 .
docker build -f myproject.Dockerfile --pull -t registry.gitlab.com/myuser/myproject/myproject:manifest-amd64 --build-arg ARCH=amd64 .
docker push registry.gitlab.com/myuser/myproject/myproject:manifest-arm64
docker push registry.gitlab.com/myuser/myproject/myproject:manifest-amd64
docker manifest create registry.gitlab.com/myuser/myproject/myproject:manifest-latest \
        --amend registry.gitlab.com/myuser/myproject/myproject:manifest-arm64 \
        --amend registry.gitlab.com/myuser/myproject/myproject:manifest-amd64
docker manifest annotate --arch arm64 registry.gitlab.com/myuser/myproject/myproject:manifest-latest registry.gitlab.com/myuser/myproject/myproject:manifest-arm64
docker manifest push registry.gitlab.com/myuser/myproject/myproject:manifest-latest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接