Как установить архитектуру для сборки докера на arm64?
У меня есть Dockerfile, который я запускаю на amd64, но хочу запустить на arm64. Так как инструмент go build принимает 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"]
Проблема в том, что полученное изображение помечается неверной архитектурой amd64 вместо arm64. Как я могу передать аргумент сборке Docker, чтобы он установил для архитектуры значение 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"
}
}
]
5 ответов
Для создания отдельных образов Docker: задайте переменную среды с помощью командной строки или изменив файл .bashrc или .zshenv. (представлено в версии 19.03.0 от марта 2019 г.)
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
Это также работает и наоборот, например, если у вас есть чип Apple M1 и вы хотите развернуть образы в среде AMD64 на базе Linux или Windows. Просто замените «linux/arm64» на «linux/amd64».
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 .
Я смог решить проблему не совсем так, как хотел, но достаточно близко.
Иметь машину amd64 Linux с докером
Настройте пользовательскую статическую систему qemu для поддержки arm https://hub.docker.com/r/multiarch/qemu-user-static/
В вашем файле Docker используйте базовый образ с поддержкой arm. Например, убунту
Создайте свой образ с помощью команды, аналогичной следующей:
сборка докера --platform arm --pull -t your_tag.
Эта команда вынудит docker вытянуть версию базового образа для руки, а также задаст архитектуру руки для вашего результирующего изображения. Но будьте осторожны, если вы используете теги с несколькими архитектурами, приведенная выше команда установит тег для версии arm. Поэтому, чтобы запустить нативную версию amd64, вам нужно будет снова потянуть тег без аргумента --platform arg.
Я собираю и запускаю образы Arm64 на хосте amd64 с помощью qemu-user. Ноdocker inspect
эти изображения Arm64 всегда показывают"Architecture": "amd64"
. Я надеюсь, что это может показать"Architecture": "arm64"
Я пыталсяDOCKER_DEFAULT_PLATFORM
и--platform=linux/arm64
, оба не работают. Я использую докер 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>
.
Ни один из предыдущих ответов мне не помог. Я собирал статический двоичный файл 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