Сборка Docker контейнеров для ARM и RISC-V архитектуры используя Buildx [обновлено 30.09.2023]

Docker контейнер всегда собирается для той платформы, на которой выполняется сборка. Но как собрать Docker образ для другой платформы, например на платформе x86 собрать образ для ARM32, ARM64 и RISC-V архитектуры? На плате Banana Pi BPI-M64 с 64-разрядным ARM процессором собирается образ для архитектуры ARM64, ARMv8, aarch64. При сборки образов для разных архитектур приходится использовать несколько устройств, что несколько неудобно. Для решения этой задачи в состав Docker CE входит инструмент Buildx, позволяющий собирать образы для различных архитектур процессоров. В публикации будет детальный разбор, как собирать Docker образы для ARM и RISC-V процессоров с дальнейшей загрузкой в публичный Docker Hub.

Оглавление

  1. Постановка задачи
  2. Buildx
  3. Инстанс сборки
  4. Сборка с помощью Buildx
  5. Загрузка образа в Docker Hub
  6. Установка Buildx для старых версий Docker
  7. Литература

Постановка задачи

Собрать Docker образ на базе Linux Alpine с ssh-сервером для архитектуры ARM64 и загрузить в публичный Docker Hub. Сборка должна выполняться на x86 процессоре, ОС Ubuntu 22.04.3 LTS, Docker version 24.0.6, build Mon Sep 4 12:31:44 2023.

Установка Docker CE для Ubuntu x86:

Buildx

Buildx — инструмент командой строки для сборки Docker контейнеров под различные архитектуры: x86, ARM, RISC-V и PowerPC. Для работы требуется Docker не ниже версии 24.0. До недавнего времени Buildx включался как экспериментальная функция. Если используется старая версия Docker, то для установки перейдите в раздел Установка Buildx для старых версий Docker.

Для проверки наличия и работы buildx выполните команду:

$ docker buildx version

Инстанс сборки

Шаг 1 — Загрузка контейнера qemu

Существуют образы типа binfmt для buildx предназначенные для сборки проектов, включающие в себя эмуляторы различных аппаратных архитектур. Рекомендуется использовать более новый образ tonistiigi/binfmt, взамен старого docker/binfmt. Установим tonistiigi/binfmt командой :

$ docker run --privileged --rm tonistiigi/binfmt --install all

После выполнения данной команды произойдет загрузка и запуск контейнера, который установит обработчик qemu. Для проверки регистрации обработчика qemu, выполнить команду  cat /proc/sys/fs/binfmt_misc/qemu-aarch64 . После выполнения команды должна появиться надпись: enabled. Ход выполнения команды:

root@ubuntuvm:~# cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64
flags: POCF
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

Если контейнер запустился и отработал в соответствии с ходом выполнения, который представлен выше, то переходите к Шаг 2 — Создание инстанса сборки.

В случае появления ошибок или проблем связанных с запуском, можете воспользоваться старой версий образа.

Установка старого образа docker/binfmt
Установка старого образа docker/binfmt

Загрузим последний доступный образ —  a7996909642ee92942dcd6cff44b9b95f08dad64.

Контейнеры docker/binfmt
docker buildx

Для загрузки образа выполнить команду:

$ sudo docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64

где, docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64 — метка a7996909… заменить на последний вариант.

Шаг 2 — Создание инстанса сборки

Необходимо создать инстанс сборки, зададим название — mybuilder. Для этого выполним команды:

$ docker buildx create --name mybuilder
$ docker buildx use mybuilder
$ docker buildx inspect --bootstrap

Если по итогу выполнения последней команды отобразилось ошибка «Error: Get «http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/buildx_buildkit_mybuilder0/json»: context deadline exceeded», то все нормально, повторно выполните последнюю команду.

В списке запущенных Docker контейнеров должен появиться контейнер с названием buildx_buildkit_mybuilder0. Для отображения запущенных контейнеров необходимо выполнить команду.

$ docker stats -a

Истанс сборки mybuilder (контейнер buildx_buildkit_mybuilder0), будет собирать контейнеры для архитектур: linux/amd64, linux/amd64/v2, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6. Из этого перечня представляет интерес:

  • linux/arm64 — для ARM64;
  • linux/arm/v7 — для ARM32;
  • linux/riscv64 — для RISC-V.

Сборка с помощью Buildx

Шаг 1 — Создание копии репозитория Alpine с ssh-сервером для сборки

Репозиторий devdotnetorg/docker-openssh-server содержит файл Dockerfile.alpine, который предназначен для сборки под архитектуру ARM64, и так же под другие архитектуры. Выполним клонирование репозитория:

$ apt-get update
$ apt-get install -y git
$ git clone https://github.com/devdotnetorg/docker-openssh-server.git

После выполнения команд появится папка  /docker-openssh-server/  с проектом.

Шаг 2 — Сборка контейнера для архитектуры ARM64

Для сборки контейнера необходимо в папке, где располагается файл Dockerfile.alpine выполнить команду:

$ cd docker-openssh-server
$ docker buildx build --platform linux/arm64 -f Dockerfile.alpine --build-arg IMAGE_VERSION=alpine:3.18 -t devdotnetorg/openssh-server:alpine-3.18-arm64 . --load

Где параметры:

  • —platform linux/arm64 — сборка для платформы linux/arm64;
  • -f Dockerfile.alpine — файл Dockerfile для сборки контейнера;
  • -t devdotnetorg/openssh-server:alpine-3.18-arm64 — название образа devdotnetorg/openssh-server, тег образа — alpine-3.18-arm64;
  • —load — загрузка образа в локальный репозиторий образов Docker.

После выполнения команды, образ можно найти в локальном репозитории Docker. Для отображения локальных образов Docker выполнить команду:

$ docker image ls

Ход выполнения:

root@ubuntuvm:~/docker-openssh-server# docker image ls
REPOSITORY                    TAG               IMAGE ID       CREATED          SIZE
devdotnetorg/openssh-server   alpine-3.18-arm64 2eb942521acc   52 seconds ago   165MB
moby/buildkit                 buildx-stable-1   9291fad3b41c   5 weeks ago      172MB
tonistiigi/binfmt             latest            354472a37893   14 months ago    60.2MB

Среди списка образов есть devdotnetorg/openssh-server , предназначенный для ARM64 архитектуры. Каждый раз собирая образы, buildx кэширует слои. Через некоторое время кэш может занимать значительное пространство на диске. Для очистки кэша используется команда:

$ docker buildx prune

Если при выполнение команды получили сообщение, что контейнер не запущен «ERROR: Error response from daemon: Container b13… is not running», то необходимо запустить контейнер следующей командой и снова повторить задачу  prune  для очистки кэша.

$ docker buildx inspect --bootstrap

Шаг 3 — Сборка контейнера для архитектуры RISC-V

Для сборки контейнера необходимо в папке, где располагается файл Dockerfile.alpine выполнить команду которую уже выполняли, только значение параметра —platform заменить на linux/riscv64:

$ docker buildx build --platform linux/riscv64 -f Dockerfile.alpine --build-arg IMAGE_VERSION=riscv64/alpine:edge -t devdotnetorg/openssh-server:alpine-riscv64 . --load

Загрузка образа в Docker Hub

Шаг 1 — Получение токена

Для аутентификации в Docker Hub необходимо получить токен. Для этого необходимо перейти на страницу hub.docker.com, войти под своей учетной записью. Перейти в раздел Account Settings. Выбрать раздел Security и нажать на кнопку New Access Token, и получить новый токен. Более подробное руководство Managing access tokens.

Шаг 2 — Авторизация Docker ID

Затем выполнить команду:

$ docker login --username [DOCKER_ID]

Где DOCKER_ID — идентификатор вашей учетной записи в Docker Hub. Ход выполнения команды:

root@ubuntuvm:~# docker login --username [DOCKER_ID]
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Шаг 2 — Сборка и загрузка образа в Docker Hub

Необходимо выполнить команду сборки, параметр —load заменить на —push. Команда:

$ docker buildx build --platform linux/arm64 -f Dockerfile.alpine --build-arg IMAGE_VERSION=alpine:3.18 -t devdotnetorg/openssh-server:alpine-3.18-arm64 . --push

Образ залит devdotnetorg/openssh-serverh, задача выполнена.

docker buildx
Загруженный образ devdotnetorg/docker-openssh-server

На одноплатном компьютере с процессором ARM64, например Banana Pi BPI-M64, для запуска контейнера выполнить команду (до выполнения команды должен быть установлен Docker — Установка Docker для ARM и 64-bit ARM (Armbian, Linux)):

$ docker run -d --name alpine-sshd -p 222:22 -e PASSWORD=123456 -v alpine-data:/data docker devdotnetorg/openssh-server:alpine-3.18-arm64

Для сборки под другие архитектуры необходимо выполнить команду:

$ docker buildx build --platform linux/arm,linux/arm64,linux/amd64 -f Dockerfile.alpine --build-arg IMAGE_VERSION=alpine:3.18 -t devdotnetorg/openssh-server:alpine . --push

Установка Buildx для старых версий Docker

Для старой версии Docker, необходимо включить Buildx как экспериментальную функцию. Это можно сделать двумя способами:

  • Добавить использование экспериментальной функции Buildx в конфигурационный файл  ~/.docker/config.json . Добавляемая строка: experimental»: «enabled»;
  • Каждый раз перед сборкой Docker образа задавать переменную окружения  DOCKER_CLI_EXPERIMENTAL=enabled .

Шаг 1 — Включение экспериментальной функции

Каждый раз в терминальной сессии для включения экспериментальной функции выполнять команду:

$ export DOCKER_CLI_EXPERIMENTAL=enabled

Не очень удобно. Поэтому добавим эту команду в скрипт автозапуска:  $HOME/.bashrc . Для этого необходимо выполнить следующую команду, которая добавит переменную окружения в конец файла:

$ printf "\nexport DOCKER_CLI_EXPERIMENTAL=enabled" >> ~/.bashrc

Необходимо обратить внимание на символ «>>». Если будет одна стрелка «>», то затрется все содержимое файла.

Дополнительно, необходимо добавить еще одну переменную окружения  DOCKER_BUILDKIT=1 :

$ printf "\nexport DOCKER_BUILDKIT=1" >> ~/.bashrc

После этого необходимо завершить текущую терминальную сессию, и снова войти в систему. После входа в систему для проверки необходимо выполнить команду отображение переменой окружения. Ход выполнения:

root@ubuntuvm:~# echo $DOCKER_CLI_EXPERIMENTAL
enabled

Шаг 2 — Загрузка утилиты buildx

В консоли для загрузки образа сборки buildx, выполнить следующие команды:

$ docker build --platform=local -o . git://github.com/docker/buildx
$ mkdir -p ~/.docker/cli-plugins
$ mv buildx ~/.docker/cli-plugins/docker-buildx

Литература

  1. buildx — GitHub docker/buildx
  2. Getting started with Docker for Arm on Linux — TIM TSAI Docker blog
  3. Building Multi-Architecture Docker Images With Buildx — Artur Klauser medium.com
  4. Managing access tokens — Docker docs
  5. Getting started with Docker for Arm using buildx on Linux — ARM Community
  6. Building Multi-Architecture Docker Images on ARM 64-bit AWS Graviton2 Processors — SCOTT ROSSILLO smartling

Вам также может понравиться

About the Author: Anton

Programistik