Оригинальная ссылка:Создавайте мультиплатформенные образы Docker с помощью buildx
В работе и в жизни нам часто может понадобиться запустить программу на разных архитектурах ЦП, например, запустить какое-то неописуемое программное обеспечение на Raspberry Pi или встроенных маршрутизаторах. Особенно после того, как Docker заполонил мир, мы можем легко развертывать различные интересные приложения через контейнеры на ARM-устройствах, не заботясь о различиях различных систем.
Но создание образов Docker на разных платформах — непростая задача: либо создайте их все на системах с различной архитектурой ЦП, либо смоделируйте различные архитектуры ЦП в текущей системе с помощью технологии виртуализации, и, наконец, вы можете подумать о способе объединения зеркал. неблагодарный.
Но, к счастью,Docker 19.03
Представлен новый экспериментальный плагин, который упрощает создание образов Docker на различных платформах. Прежде чем представить эту новую функцию, давайте рассмотрим основы создания программ для разных архитектур ЦП.
1. Методы компиляции программ для разных архитектур ЦП
Начнем с краткого обзора различных современных подходов к компиляции программ для разных архитектур ЦП.
Способ 1: компилировать непосредственно на целевом оборудовании
Если у вас есть доступ к системе с целевой архитектурой ЦП, и эта операционная система поддерживает различные инструменты, необходимые для запуска сборки, вы можете скомпилировать программу непосредственно в целевой системе.
В качестве примера возьмем создание образа Docker, вы можете установить Docker на Raspberry Pi, а затем использоватьDockerfile
Постройте образ платформы руки напрямую.
Что делать, если у меня нет доступа к системе с целевой архитектурой ЦП? Есть ли способ как-то собрать программу для целевой архитектуры процессора прямо в текущей системе? Пожалуйста, смотрите ниже...
Способ 2: имитация целевого оборудования
Помните аркадные игры, в которые мы играли в различных интернет-кафе и бильярдных в детстве? Вот картинка на память:
Что, если теперь мы хотим пережить аркадные игры, в которые играли раньше? В это время вам нужно использовать эмулятор (Emulator). С помощью эмуляторов мы можем повернуть время вспять и испытать удовольствие от классических игр.
Помимо игр, эмуляторы также можно использовать для создания программ на разных архитектурах ЦП. Наиболее часто используемые симуляторы имеют открытый исходный код.QEMU, QEMU поддерживает множество распространенных архитектур ЦП, в том числеARM
,Power-PC
а такжеRISC-V
Ждать. Эмулируя полную операционную систему, можно создать универсальную виртуальную машину ARM, которая может загружать Linux, настраивать среду разработки и компилировать программы внутри виртуальной машины.
Тем не менее, эмулировать всю ОС по-прежнему немного расточительно, потому что в этом режиме QEMU будет эмулировать всю систему, включая оборудование, такое как таймеры, контроллеры памяти, контроллеры шины и т. д. Но компилятору вообще не нужно заботиться об этом, и его можно немного упростить.
Способ 3: смоделируйте пользовательское пространство целевого оборудования с помощью binfmt_misc
В Linux,QEMU
В дополнение к симуляции полной операционной системы существует еще один режим, называемый用户态模式
(Пользовательский мод). В этом режиме QEMU будет проходитьbinfmt_miscРегистрирует обработчик двоичного преобразования в ядре Linux и динамически преобразует двоичные файлы во время работы программы, переводя системные вызовы из целевой архитектуры ЦП в архитектуру ЦП текущей системы по мере необходимости. Конечный результат выглядит как локальный запуск двоичного файла для целевой архитектуры ЦП.
Через пользовательский режим QEMU мы можем создавать легковесные виртуальные машины (chrootили контейнер), а затем скомпилировать программу в системе виртуальной машины так же просто, как локальная компиляция. Как мы увидим позже, именно этот метод используется для создания образов Docker на разных платформах.
Способ 4: используйте кросс-компилятор
Наконец, представлен метод, обычно используемый в сообществе встраиваемых систем: кросс-компиляция.
Кросс-компилятор — это компилятор, специально разработанный для работы на данной системной платформе, но способный компилировать исполняемые файлы для другой системной платформы. Например,amd64
Кросс-компилятор C++ в системе на базе Linux может компилироваться для работы наaarch64
Исполняемые файлы на встроенных устройствах (64-битной архитектуры ARM). Чтобы привести еще один реальный пример, приложения для устройств Android в основном компилируются таким образом.
С точки зрения производительности этот метод ничем не отличается от метода 1, так как не требуется симулятор и почти нет потери производительности. Но кросс-компиляция не универсальна, ее сложность зависит от языка, который использует программа, если вы используете Golang, то это супер просто.
В эпоху универсальных контейнеров, когда мы говорим о сборке, мы подразумеваем не только сборку одного исполняемого файла, но и сборку образа контейнера. А сборка образов контейнеров сложнее вышеперечисленных способов, плюс сложность самого Docker, это чуть ли не давняя проблема.
Однако с введением нового экспериментального плагина создавать образы Docker для мультиплатформенных архитектур стало намного проще, чем раньше.Что же касается этого плагина, мы подробно расскажем о нем ниже.
2. Создайте мультиплатформенный образ Docker
Воспользуйтесь преимуществами плагинов, представленных в Docker 19.03.buildx, вы можете легко создавать многоплатформенные образы Docker. buildx этоdocker build ...
Замена Command следующего поколения, в которой используетсяBuildKitПолная функциональность расширенногоdocker build
функция.
Вот как это использовать всего за несколько минутbuildx
Создавайте образы Docker для разных платформ. Выполните следующие действия:
Включить плагин buildx
Хотите использоватьbuildx
, сначала убедитесь, что версия Docker не ниже19.03
, но и установив переменную окруженияDOCKER_CLI_EXPERIMENTAL
включить. Плагин buildx можно включить для текущего терминала с помощью следующей команды:
🐳 → export DOCKER_CLI_EXPERIMENTAL=enabled
Убедитесь, что он включен:
🐳 → docker buildx version
github.com/docker/buildx v0.3.1-tp-docker 6db68d029599c6710a32aa7adcba8e5a344795a7
Если переменная окружения установлена в некоторых системахDOCKER_CLI_EXPERIMENTAL
не работает (т.Arch Linux), вы можете выбрать компиляцию из исходного кода:
🐳 → export DOCKER_BUILDKIT=1
🐳 → docker build --platform=local -o . git://github.com/docker/buildx
🐳 → mkdir -p ~/.docker/cli-plugins && mv buildx ~/.docker/cli-plugins/docker-buildx
включить binfmt_misc
Если вы используете Docker Desktop (MacOS и Windows), он включен по умолчанию.
binfmt_misc
, вы можете пропустить этот шаг.
Если вы используете Linux, вам нужно включить его вручнуюbinfmt_misc
. Большинство дистрибутивов Linux легко включить, но есть более простой способ напрямую запустить привилегированный контейнер с написанным в нем сценарием установки:
🐳 → docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
Рекомендуется обновить версию ядра Linux выше 4.x, особенно для пользователей CentOS могут возникнуть ошибки.
Убедитесь, что binfmt_misc включен:
🐳 → ls -al /proc/sys/fs/binfmt_misc/
总用量 0
总用量 0
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-aarch64
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-arm
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-ppc64le
-rw-r--r-- 1 root root 0 11月 18 00:12 qemu-s390x
--w------- 1 root root 0 11月 18 00:09 register
-rw-r--r-- 1 root root 0 11月 18 00:12 status
Убедитесь, что соответствующий процессор включен:
🐳 → cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b7
mask ffffffffffffff00fffffffffffffffffeffff
Переключитесь с построителя по умолчанию на мультиплатформенный построитель
По умолчанию Docker будет использовать сборщики, которые не поддерживают многопроцессорные архитектуры, и нам нужно переключаться вручную.
Сначала создайте новый билдер:
🐳 → docker buildx create --use --name mybuilder
Запустите конструктор:
🐳 → docker buildx inspect mybuilder --bootstrap
[+] Building 5.0s (1/1) FINISHED
=> [internal] booting buildkit 5.0s
=> => pulling image moby/buildkit:buildx-stable-1 4.4s
=> => creating container buildx_buildkit_mybuilder0 0.6s
Name: mybuilder
Driver: docker-container
Nodes:
Name: mybuilder0
Endpoint: unix:///var/run/docker.sock
Status: running
Platforms: linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
Глядя на используемый в настоящее время сборщик и поддерживаемые им архитектуры ЦП, вы можете видеть, что поддерживается множество архитектур ЦП:
🐳 → docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
default docker
default default running linux/amd64, linux/386
Создавайте мультиплатформенные образы
Теперь мы можем создавать образы, поддерживающие несколько архитектур ЦП! Предположим, есть исходный код простой программы golang:
🐳 → cat hello.go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Printf("Hello, %s!\n", runtime.GOARCH)
}
Создайте Dockerfile для контейнеризации приложения:
🐳 → cat Dockerfile
FROM golang:alpine AS builder
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o hello .
FROM alpine
RUN mkdir /app
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]
Это многоэтапный файл Dockerfile, который использует компилятор Go для сборки приложения и копирует встроенные двоичные файлы в образ alpine.
Теперь вы можете использовать buildx для создания образа Docker, поддерживающего мультиархитектуру arm, arm64 и amd64, и отправить его наDocker Hub:
🐳 → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm,linux/arm64,linux/amd64 . --push
нужно пройти заранее
docker login
Команда для входа в систему для аутентификации Docker Hub.
теперь можно пройтиdocker pull mirailabs/hello-arch
Извлеките образ, который вы только что создали, и Docker извлечет соответствующий образ на основе архитектуры вашего процессора.
Принцип, лежащий в основе этого, также очень прост, как упоминалось ранее, buildx пройдетQEMU
а такжеbinfmt_misc
Создайте 3 разных образа для 3 разных архитектур ЦП (arm, arm64 и amd64). После того, как сборка завершена,manifest list, который содержит указатели на 3 зеркала.
Если вы хотите сохранить построенный образ локально, вы можетеtype
Назначенdocker
, но должны создавать разные образы для разных архитектур ЦП и не могут быть объединены в один образ, то есть:
🐳 → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm -o type=docker .
🐳 → docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm64 -o type=docker .
🐳 → docker buildx build -t yangchuansheng/hello-arch --platform=linux/amd64 -o type=docker .
Тестируйте мультиплатформенные образы
Так как ранее он был включенbinfmt_misc
, теперь мы можем запустить образ Docker для любой архитектуры ЦП, поэтому мы можем проверить 3 ранее сгенерированных образа на наличие проблем в нашей локальной системе.
Сначала перечислите каждое зеркалоdigests
:
🐳 → docker buildx imagetools inspect yangchuansheng/hello-arch
Name: docker.io/yangchuansheng/hello-arch:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:ec55f5ece9a12db0c6c367acda8fd1214f50ee502902f97b72f7bff268ebc35a
Manifests:
Name: docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Name: docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Запустите каждое изображение и посмотрите вывод:
🐳 → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639
Hello, arm!
🐳 → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d
Hello, arm64!
🐳 → docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2
Hello, amd64!
Так круто!
3. Резюме
Подводя итог, эта статья расскажет вам о проблемах запуска программного обеспечения на разных архитектурах ЦП иbuildx
Как помочь нам решить некоторые из этих проблем. использоватьbuildx
, мы можем создать образ Docker, поддерживающий несколько архитектур ЦП, и отправить его в Docker Hub без каких-либо изменений в Dockerfile. Любая система с установленным Docker может извлекать образы, соответствующие архитектуре процессора.
В будущем buildx может статьdocker build
Часть команды, в конечном итоге все вышеупомянутые функции станут функциями по умолчанию, погружение в инфраструктуру для кросс-компиляции программ станет древней глупостью.
4. Ссылки
- Building Multi-Arch Images for Arm and x86 with Docker Desktop
- Getting started with Docker for Arm on Linux
- Leverage multi-CPU architecture support
Публичный аккаунт WeChat
Отсканируйте QR-код ниже, чтобы подписаться на официальную учетную запись WeChat, и ответьте на официальную учетную запись ◉Добавить группу◉, чтобы присоединиться к нашей облачной коммуникационной группе и обсудить облачные технологии с Сунь Хунляном, директором Чжаном, Ян Мином и другими важными шишками.