Кейс: Docker-сборка для ARM и x86

Ситуация

Интеграционное окружение собиралось и запускалось на x86, но ломалось на ARM-машинах. Один и тот же проект использовал базовые образы Java и PostgreSQL, доступные не для всех архитектур.

Ручная замена образов решала проблему только на компьютере конкретного разработчика и быстро забывалась.

Что я проверил

  • архитектуру хоста через uname -m;
  • поддерживаемые платформы базовых образов;
  • где именно Dockerfile фиксирует имя образа;
  • на каком этапе Maven собирает контейнер для интеграционных тестов;
  • какие файлы приходится менять вручную перед запуском.

Причиной оказалась не Java и не тесты. Сборка была жёстко связана с одним вариантом образа.

Мой вклад

Я вынес Java-образ в аргумент Dockerfile:

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

Затем добавил профили сборки для ARM и x86. Профиль выбирал подходящий образ и передавал его как build argument. Для контейнера БД подготовил отдельный шаг, который выбирал совместимый образ перед интеграционным запуском.

Результат

Выбор платформы стал частью воспроизводимой сборки. Разработчику больше не требовалось вручную править Dockerfile при переходе между ARM и x86.

Что важно помнить

  • тег образа не означает, что у него есть manifest для нужной архитектуры;
  • архитектура хоста, build platform и target platform могут различаться;
  • эмуляция помогает не всегда и заметно замедляет сборку;
  • заменять внутренний образ публичным можно только с учётом состава и настроек образа;
  • выбор образа должен быть виден в логах сборки.

Связанные заметки