Docker manifest — это экспериментальная команда для создания образов docker, поддерживающих несколько архитектур. Давайте посмотрим, как она работает, и сравним ее с docker buildx.
В 2019 году docker buildx был создан как способ построения мультиархитектурных образов. В то время у разработчиков не было Arm в облаке или на рабочем столе. Проекты были заинтересованы в архитектуре Arm, но как вторичный вариант для AWS Graviton или даже Raspberry Pi. С помощью buildx одна команда сборки создает образ с несколькими архитектурами. В некоторых случаях для сборки даже не требуется машина Arm.
Сегодня разработчики используют архитектуру Arm на своем рабочем столе и в облаке. Новаторский успех процессоров AWS Graviton побудил разработчиков попробовать Graviton на практике. Популярность компьютеров Mac с кремнием Apple означает, что у многих разработчиков на столе стоит та же архитектура. Сегодня я расскажу, как создавать многоархивные образы с помощью команды docker manifest. Я обнаружил, что это самый простой способ создания многоархивных образов для многих проектов.
Справочная информация
Docker buildx предоставляет команду сборки для создания образов для нескольких архитектур. Я в основном использую arm64 и amd64. Если вы используете другие архитектуры, концепция может быть легко расширена.
Сложность buildx заключается в том, что он использует эмуляцию, кросс-компиляцию или удаленный сборщик для целевых архитектур, которые не соответствуют машине сборки. Эмуляция отлично работает для создания образов, которые в основном копируют и устанавливают файлы, но она может страдать от функциональных проблем или проблем с производительностью при создании более сложных образов. Иногда кросс-компиляция выполняется легко, но иногда с трудом. Использование удаленного сборщика неудобно для тестирования изменений. Изменение настроек удаленного сборщика во время тестирования может сбить с толку.
Docker buildx также сбивает с толку разработчиков, которые ожидают, что локальный образ будет немедленно запущен после успешной сборки. Поскольку buildx предназначен для нескольких архитектур, его необходимо сохранять в репозиторий, а не в локальное хранилище. Для этого требуется push в хранилище, а затем pull для запуска. Есть и другие обходные пути, но модель использования отличается от того, что ожидают многие разработчики. Поиск на Stack Overflow и GitHub подтверждает, что отсутствие изображения после успешного запуска buildx — распространенный вопрос.
Я трачу большую часть своего времени на архитектуру Arm. Все меньшее число проектов требует поддержки amd64, но когда это происходит, я стараюсь избегать buildx. Docker buildx — один из способов решения проблем, связанных с несколькими архитектурами, но docker manifest кажется мне проще.
Давайте посмотрим, как это работает.
Docker manifest
Docker включает экспериментальную функцию под названием docker manifest. Пожалуйста, имейте в виду, что эта функция является экспериментальной и не рекомендуется для использования в производстве.
Docker manifest обеспечивает другой способ работы. Он позволяет создавать отдельные образы для каждой архитектуры, которые могут быть объединены в многоархитектурный образ, когда приходит время поделиться. Это позволяет мне собирать и тестировать на любой архитектуре и отложить использование multi-arch на потом. Когда приходит время поделиться многоархитектурным образом, он может быть создан за считанные секунды с помощью docker manifest. Docker manifest также позволяет легко обновлять одну из архитектур без эмуляции или удаленных сборщиков.
Давайте проведем небольшое сравнение между buildx и docker manifest.
Вот небольшой пример Dockerfile.
FROM alpine AS builder
RUN apk add build-base
WORKDIR /home
COPY hello.c .
RUN gcc "-DARCH="`uname -a`"" hello.c -o hello
FROM alpine
WORKDIR /home
COPY --from=builder /home/hello .
CMD ["./hello"]
Dockerfile компилирует и запускает программу hello world на C.
#include <stdio.h>
#include <stdlib.h>
#ifndef ARCH
#define ARCH "Undefined"
#endif
int main()
{
printf("Hello Arm Developers, architecture from uname is %sn", ARCH);
switch (sizeof(void *))
{
case 4:
printf("32-bit userspacen");
break;
case 8:
printf("64-bit userspacen");
break;
default:
printf("unknown userspacen");
}
exit(0);
}
Скопируйте Dockerfile и hello.c на свой компьютер для выполнения следующих шагов.
Давайте посмотрим, как использовать его с помощью buildx для сборки мультиархитектурного образа.
Docker buildx
Использование buildx подразумевает настройку билдера и выполнение команды buildx.
Ниже приведен сценарий, показывающий, как использовать buildx. Скопируйте файл, измените переменную HUBU на ваше имя пользователя Docker Hub и запустите скрипт, чтобы попробовать.
#!/bin/bash
HUBU=hubuser
IMG=hello-world
docker buildx create --name mybuilder
docker buildx use mybuilder
docker buildx build --platform linux/amd64,linux/arm64 -t $HUBU/$IMG --push .
Сценарий автоматически отправляет многоархивный образ в Docker Hub. Без аргумента push результаты будут недоступны. Достаточно легко извлечь образ и запустить его, но при больших размерах образа требуется время для отправки в реестр и извлечения обратно.
Существует множество руководств по использованию buildx, если вы хотите узнать больше.
Манифест Docker
Команда docker manifest полезна для объединения нескольких существующих образов в один мультиархитектурный образ.
Чтобы отслеживать образы, я использую тег image для указания архитектуры.
Чтобы собрать тот же Dockerfile без buildx, используйте эту команду. Получится один образ, только для архитектуры текущей машины.
docker build -t hello-world:$(arch) .
Образ доступен для запуска локально. На AWS Graviton тег будет aarch64, чтобы отличить его от той же команды, запущенной на машине x86_64.
После создания образа на каждой машине, которую вы хотите поддерживать, отметьте образы для учетной записи Docker Hub и проведите push. Снова измените имя пользователя Docker Hub, чтобы попробовать.
docker tag hello-world:$(arch) jasonrandrews/hello-world:$(arch)
docker push jasonrandrews/hello-world:$(arch)
На изображении ниже показаны обе метки в Docker Hub.
Последним шагом будет объединение двух меток в один мультиархитектурный образ.
docker manifest create jasonrandrews/hello-world:latest
--amend jasonrandrews/hello-world:aarch64
--amend jasonrandrews/hello-world:x86_64
docker manifest push --purge jasonrandrews/hello-world:latest
Опция purge не нужна в первый раз, но я обнаружил, что для обновления одного из образов и обновления многоархитектурного образа она необходима.
После обновления манифеста будет доступен новый многоархивный образ с последним тегом. Вытаскивание hello-world:latest из любой архитектуры теперь работает, и пользователю не нужно обращать внимание на то, какой компьютер он использует.
Резюме
Экспериментальная команда docker manifest предлагает способ создания мультиархитектурных образов путем объединения нескольких образов с помощью манифеста. Docker manifest предоставляет дополнительные возможности, не рассмотренные здесь, и полезен для создания, проверки и изменения списков манифестов. По мере развития команды docker manifest и расширения использования AWS Graviton разработчиками, она предоставляет еще один способ создания образов docker.
Попробуйте и посмотрите, как это работает.