Мультиплатформенные образы
Образы Docker могут поддерживать несколько платформ, что означает, что один образ может содержать варианты для разных архитектур, а иногда и для разных операционных систем, например, Windows.
При запуске образа с поддержкой нескольких платформ docker
автоматически выбирает образ, соответствующий вашей ОС и архитектуре.
Большинство официальных образов Docker на Docker Hub содержат разнообразие архитектур. Например, образ busybox
поддерживает amd64
, arm32v5
, arm32v6
, arm32v7
, arm64v8
, i386
, ppc64le
и s390x
. При запуске этого образа на компьютере x86_64
/amd64
извлекается и запускается опция amd64
.
Создание многоплатформенных образов
Сейчас Docker как никогда упрощает разработку контейнеров на серверах и устройствах Arm и для них. Используя стандартные инструменты и процессы Docker, вы можете приступить к созданию, продвижению, извлечению и запуску образов на различных вычислительных архитектурах. В большинстве случаев вам не придется вносить какие-либо изменения в файлы Docker или исходный код, чтобы начать сборку для Arm.
BuildKit с Buildx предназначен для сборки для нескольких платформ, а не только для архитектуры и операционной системы, на которой работает пользователь, вызывающий сборку.
Когда вы вызываете сборку, вы можете установить флаг --platform
, чтобы указывает целевую платформу для вывода сборки (например, linux/amd64
, linux/arm64
или darwin/amd64
).
Когда текущий экземпляр сборщика поддерживается драйвером docker-container
, вы можете указывает несколько платформ вместе. В этом случае создаётся список манифестов, содержащий образы для всех указанных архитектур. Когда вы используете данный образ в запуск Docker или служба докеров, Docker выбирает правильный образ на основе платформы узла.
Вы можете создавать многоплатформенные образы, используя три различные стратегии, которые поддерживаются Buildx и Dockerfiles:
Использование поддержки эмуляции QEMU в ядре
Построение на нескольких собственных узлах с использованием одного экземпляра построителя
Использование этапа в Dockerfile для кросс-компиляции на разных архитектурах
QEMU — самый простой способ начать работу, если ваш узел уже поддерживает его (например. если вы используете Docker Desktop). Он не требует изменений в вашем Dockerfile, а BuildKit автоматически определяет доступные вторичные архитектуры. Когда BuildKit необходимо запускает бинарник для другой архитектуры, он автоматически загружает его через бинарник, зарегистрированный в обработчике binfmt_misc
.
Чтобы двоичные файлы QEMU, зарегистрированные с помощью binfmt_misc
в операционной системе хоста, могли прозрачно работать внутри контейнеров, они должны быть статически скомпилированы и зарегистрированы с флагом fix_binary
. Для этого требуется ядро >= 4.8 и поддержка binfmt >= 2.1.7. Вы можете проверяет правильность регистрации, проверив, есть ли F
среди флагов в /proc/sys/fs/binfmt_misc/qemu-*
. Хотя Docker Desktop поставляется с предварительно настроенной поддержкой binfmt_misc
для дополнительных платформ, для других установок его, вероятно, необходимо установить с использованием образа tonistiigi/binfmt.
$ docker run --privileged --rm tonistiigi/binfmt --install all
Использование нескольких собственных узлов обеспечивает лучшую поддержку более сложных случаев, которые не обрабатываются QEMU, и обычно имеет лучшую производительность. Вы можете добавить дополнительные узлы к экземпляру сборщика с помощью флага --append
.
Предположим, что контексты node-amd64
и node-arm64
существуют в docker context ls
;
$ docker buildx create --use --name mybuild node-amd64
mybuild
$ docker buildx create --append --name mybuild node-arm64
$ docker buildx build --platform linux/amd64,linux/arm64 .
Наконец, в зависимости от вашего проекта, используемый вами язык может иметь хорошую поддержку кросс-компиляции. В этом случае многоэтапные сборки в Dockerfiles можно эффективно использовать для сборки двоичных файлов для платформы, указанной с помощью --platform
, используя родную архитектуру узла сборки. Список аргументов сборки, таких как BUILDPLATFORM
и TARGETPLATFORM
, автоматически доступен внутри вашего Dockerfile и может быть использован процессами, запущенными в рамках вашей сборки.
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
FROM alpine
COPY --from=build /log /log
Начало работы
Запускает Команда docker buildx ls, чтобы перечислить существующих строителей:
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default * docker
default default running 20.10.17 linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
Здесь отображается встроенный драйвер по умолчанию, который использует серверные компоненты BuildKit, встроенные непосредственно в движок docker, также известный как драйвер Docker.
Создаёт новый билдер с помощью драйвер docker-контейнера, который даст вам доступ к более сложным функциям, таким как многоплатформенные сборки и более продвинутые экспортеры кэша, которые в настоящее время не поддерживаются в стандартном драйвере docker
:
$ docker buildx create --name mybuilder --driver docker-container --bootstrap
mybuilder
Переключитесь на нового строителя:
$ docker buildx use mybuilder
Примечание
В качестве альтернативы выполняет docker buildx create --name mybuilder --driver docker-container --bootstrap --use
, чтобы создать новый конструктор и переключиться на него с помощью одной команды.
И осмотрите его:
$ docker buildx inspect
Name: mybuilder
Driver: docker-container
Nodes:
Name: mybuilder0
Endpoint: unix:///var/run/docker.sock
Status: running
Buildkit: v0.10.4
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
Теперь, снова перечислив существующих строителей, мы видим, что наш новый строитель зарегистрирован:
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder docker-container
mybuilder0 unix:///var/run/docker.sock running v0.10.4 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default * docker
default default running 20.10.17 linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
Пример
Протестируйте рабочий процесс, чтобы убедиться, что вы можете создавать, отправлять и запускать многоплатформенные образы. Создаёт простой пример Dockerfile, постройте несколько вариантов образов и отправить их в Docker Hub.
В следующем примере используется один Dockerfile
для создания образа Alpine с установленным cURL для нескольких архитектур:
# syntax=docker/dockerfile:1
FROM alpine:3.16
RUN apk add curl
Собирает Dockerfile с помощью buildx, передав список архитектур для сборки:
$ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t <username>/<image>:latest --push .
...
#16 exporting to image
#16 exporting layers
#16 exporting layers 0.5s done
#16 exporting manifest sha256:71d7ecf3cd12d9a99e73ef448bf63ae12751fe3a436a007cb0969f0dc4184c8c 0.0s done
#16 exporting config sha256:a26f329a501da9e07dd9cffd9623e49229c3bb67939775f936a0eb3059a3d045 0.0s done
#16 exporting manifest sha256:5ba4ceea65579fdd1181dfa103cc437d8e19d87239683cf5040e633211387ccf 0.0s done
#16 exporting config sha256:9fcc6de03066ac1482b830d5dd7395da781bb69fe8f9873e7f9b456d29a9517c 0.0s done
#16 exporting manifest sha256:29666fb23261b1f77ca284b69f9212d69fe5b517392dbdd4870391b7defcc116 0.0s done
#16 exporting config sha256:92cbd688027227473d76e705c32f2abc18569c5cfabd00addd2071e91473b2e4 0.0s done
#16 exporting manifest list sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48 0.0s done
#16 ...
#17 [auth] <username>/<image>:pull,push token for registry-1.docker.io
#17 DONE 0.0s
#16 exporting to image
#16 pushing layers
#16 pushing layers 3.6s done
#16 pushing manifest for docker.io/<username>/<image>:latest@sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48
#16 pushing manifest for docker.io/<username>/<image>:latest@sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48 1.4s done
#16 DONE 5.6s
Примечание
<username>
должен быть действительным Docker ID, а<image>
— действительным репозиторием на Docker Hub.Флаг
--platform
сообщает buildx о необходимости создания образов Linux для 64-битной архитектуры AMD, 64-битной архитектуры Arm и архитектуры Armv7.Флаг
--push
создаёт многоархивный манифест и размещает все образы в Docker Hub.
Осмотрите образ с помощью команды docker buildx imagetool:
$ docker buildx imagetools inspect <username>/<image>:latest
Name: docker.io/<username>/<image>:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48
Manifests:
Name: docker.io/<username>/<image>:latest@sha256:71d7ecf3cd12d9a99e73ef448bf63ae12751fe3a436a007cb0969f0dc4184c8c
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: docker.io/<username>/<image>:latest@sha256:5ba4ceea65579fdd1181dfa103cc437d8e19d87239683cf5040e633211387ccf
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.io/<username>/<image>:latest@sha256:29666fb23261b1f77ca284b69f9212d69fe5b517392dbdd4870391b7defcc116
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Образ теперь доступен на Docker Hub с тегом <username>/<image>:latest
. Вы можете использовать данный образ для запуска контейнера на ноутбуках Intel, инстансах Amazon EC2 Graviton, Raspberry Pis и на других архитектурах. Docker извлекает правильный образ для текущей архитектуры, поэтому на Raspberry PI запускается 32-битная версия Arm, а на инстансах EC2 Graviton — 64-битная Arm.
Дайджест идентифицирует полностью квалифицированный опция образа. На Docker Desktop можно также запускать образы, предназначенные для другой архитектуры. Например, при запуске следующего образа на macOS:
$ docker run --rm docker.io/<username>/<image>:latest@sha256:2b77acdfea5dc5baa489ffab2a0b4a387666d1d526490e31845eb64e3e73ed20
uname -m aarch64
$ docker run --rm docker.io/<username>/<image>:latest@sha256:723c22f366ae44e419d12706453a544ae92711ae52f510e226f6467d8228d191 uname -m
armv7l
В приведённом выше примере uname -m
возвращает aarch64
и armv7l
, как и ожидалось, даже при выполнении команд на собственной машине разработчика macOS или Windows.
Поддержка на Docker Desktop
Docker Desktop обеспечивает поддержку мультиархитектуры binfmt_misc
, что означает, что вы можете запускать контейнеры для различных архитектур Linux, таких как arm
, mips
, ppc64le
и даже s390x
.
Это не требует какой-либо специальной настройки в самом контейнере, поскольку он использует qemu-static из Docker for Mac VM. Из-за этого вы можете запускать контейнер ARM, например варианты arm32v7
или ppc64le
образа busybox.