Docker описывает многоплатформенный образ как набор вариантов, среди которых могут быть linux/amd64 и linux/arm64 — это уже достаточная причина не начинать диагностику с установки Rosetta. Если Docker amd64-образ не запускается на Mac, сначала проверьте манифест и фактическую платформу контейнера. При наличии arm64-варианта запускайте его нативно; если доступен только amd64, временно проверяйте эмуляцию. Для долгой научной работы собирайте multi-arch-образ или оставляйте нативный x86-узел. Официальное описание многоплатформенных образов Docker.

Эта статья предназначена:

  • аспирантам, которым нужно запустить старый образ авторов статьи на новом Mac;
  • разработчикам научного ПО, доставляющим один проект пользователям x86 и arm64;
  • техническим сотрудникам лабораторий, распределяющим работу между удалённым Apple Silicon Mac, существующим x86-сервером и двойной инфраструктурой.

Сначала определите, какой именно сбой вы наблюдаете

На практике смешиваются три разных уровня:

  1. Docker сообщает о несовпадении платформы.
  2. Контейнер запускается, но завершается с exec format error.
  3. Контейнер остаётся активным, однако Python, R, Java или нативное расширение падает при реальном анализе.

Это не одна и та же проблема. Предупреждение означает архитектурное расхождение. Ошибка exec format error обычно указывает, что загрузчик получил исполняемый файл неподходящей архитектуры. Успешный запуск контейнера подтверждает только работу entrypoint, но не корректность научного результата.

Начните с фиксации базовых фактов:

uname -m
docker version
docker buildx version
docker buildx imagetools inspect IMAGE:TAG
docker image inspect IMAGE:TAG --format '{{.Architecture}}/{{.Os}}'

uname -m показывает архитектуру macOS-хоста. Команда docker buildx imagetools inspect позволяет увидеть платформы, опубликованные в манифесте образа. Если в списке есть linux/arm64, Docker обычно может выбрать подходящий вариант автоматически. Если присутствует только linux/amd64, автоматического нативного варианта нет.

Для проверки уже созданного контейнера используйте:

docker inspect CONTAINER \
  --format '{{.Platform}} {{.Config.Image}} {{.State.Status}}'

Сопоставьте четыре значения: архитектуру Mac, платформу образа, платформу контейнера и архитектуру проблемного бинарника. Не заменяйте эту проверку фразой «Docker Desktop установлен правильно» — установка приложения не доказывает совместимость конкретного научного образа. Требования к Docker Desktop для Mac и поддерживаемые варианты установки приведены в официальной документации Docker.

Важно. Предупреждение о платформе — сигнал для проверки, а не автоматический вердикт «контейнер неработоспособен». Но исчезновение предупреждения после запуска с --platform также не является доказательством воспроизводимости.

Первый маршрут: отделите нативный запуск от временной эмуляции

Если манифест содержит arm64-вариант, попробуйте его без принудительного выбора:

docker run --rm IMAGE:TAG

Если образ неоднозначен или вы хотите зафиксировать проверку, укажите платформу явно:

docker run --rm --platform=linux/arm64 IMAGE:TAG

Параметр --platform относится к официальным аргументам docker run; его назначение описано в справочнике Docker для запуска контейнеров.

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

docker run --rm --platform=linux/amd64 IMAGE:TAG

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

После старта проверьте не только процесс контейнера, но и научный маршрут:

docker run --rm --platform=linux/amd64 \
  -v "$PWD/data:/work/data" \
  -v "$PWD/results:/work/results" \
  IMAGE:TAG \
  sh -lc 'python --version && ./run-analysis.sh /work/data /work/results'

Приёмка должна включать:

  • выполнение настоящего entrypoint;
  • запуск ключевой программы;
  • чтение входного образца;
  • создание ожидаемых файлов;
  • проверку формата и контрольной суммы результата;
  • сохранение полного журнала ошибок.

Если контейнер просто перешёл в состояние Exited 0, но не создал результат, научная задача не пройдена.

Когда появляется exec format error

Ошибка часто возникает ещё до выполнения основного анализа. Типичный пример — arm64-слой содержит скрипт, который вызывает заранее скачанный amd64-бинарник. В другом случае образ собран на x86, а в него вручную скопировали исполняемый файл из системного каталога.

Проверяйте entrypoint и оболочку:

docker image inspect IMAGE:TAG \
  --format 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'

docker run --rm --platform=linux/amd64 \
  --entrypoint /bin/sh IMAGE:TAG -lc \
  'uname -m; command -v python; file "$(command -v python)"'

Затем исследуйте подозрительный файл:

docker run --rm --platform=linux/amd64 \
  --entrypoint /bin/sh IMAGE:TAG -lc \
  'file /path/to/suspect-binary'

Если в минимальном образе нет команды file, не устанавливайте пакеты вслепую. Сначала сохраните журнал, хэш образа и список слоёв. Для воспроизводимости важнее знать, что именно проверялось, чем получить случайно изменённый контейнер.

Разделяйте три архитектуры:

  • архитектуру опубликованного образа;
  • архитектуру базового слоя;
  • архитектуру отдельных библиотек и расширений.

Например, Python-интерпретатор может быть arm64, а скомпилированный модуль — amd64. Аналогичный конфликт встречается в R-пакетах с нативным кодом, Java JNI-библиотеках и подключаемых ускорителях. Повторная установка Python или R не исправит библиотеку, если установщик снова получает пакет не той архитектуры.

Сначала соберите минимальный тест:

python -c "import MODULE; print(MODULE.__file__)"
R -q -e 'library(PACKAGE); sessionInfo()'
java -version

После этого прогоните небольшой обезличенный набор данных. Сравнивайте не только отсутствие исключения, но и структуру результата, число записей, контрольные суммы там, где это допустимо, и версии зависимостей. Если проект использует случайность, зафиксируйте seed. Если результат всё равно расходится, сохраните обе ветки и не перезаписывайте старый образ.

Как отличить медленную эмуляцию от настоящего зависания

Сборка старого amd64-образа на Apple Silicon может долго загружать слои, компилировать расширения и выполнять тесты через эмуляцию. Одного наблюдения «процесс долго не меняется» недостаточно, чтобы объявить сборку зависшей.

Снимите сведения о текущем builder:

docker buildx ls
docker buildx inspect --bootstrap
docker info

Проверьте:

  • какой builder выбран по умолчанию;
  • какие платформы он заявляет;
  • запускается ли его виртуальная машина;
  • на каком шаге остановились логи;
  • меняется ли объём скачанных данных;
  • есть ли процесс компилятора внутри контейнера.

Для сборки с явной платформой используйте:

docker buildx build \
  --platform=linux/amd64 \
  --progress=plain \
  -t research:test-amd64 .

Параметр --platform и режим подробного вывода описаны в документации команды Docker Buildx build.

Сохраните отдельно четыре наблюдения: скорость загрузки, скорость компиляции, прохождение тестов и время запуска программы. Не называйте эти значения универсальной производительностью — без одинакового узла, образа и данных такое сравнение некорректно.

Важна и виртуализация. Docker предупреждает, что доступные функции зависят от выбранного виртуального механизма; Docker VMM, например, имеет собственные ограничения и не поддерживает Rosetta. Проверяйте актуальное состояние по документации Docker о виртуальных машинах, а не по старому скриншоту из форума. Apple описывает Rosetta как технологию перевода приложений Intel для компьютеров с Apple Silicon, но это не обещание совместимости каждого контейнерного стека. Подробности есть в документе Apple о Rosetta 2.

Как перейти от временного запуска к multi-arch-образу

Эмуляция полезна как диагностический мост. Для регулярной работы лаборатории лучше устранить архитектурную зависимость.

Начните с Dockerfile. Ищите:

  • базовый образ, закреплённый на amd64;
  • URL, в котором архитектура зашита вручную;
  • скачивание готового x86_64-архива;
  • вызов uname -m во время сборки;
  • копирование бинарников из локального каталога;
  • нативные расширения, компилируемые без указания целевой платформы.

Не добавляйте бездумно FROM --platform=linux/amd64. Docker предупреждает, что постоянное закрепление платформы в FROM может мешать multi-platform-сборке и скрывать проблему. Соответствующее правило проверки описано в официальном объяснении FROM с фиксированной платформой.

Для условной логики используйте аргументы BuildKit:

ARG TARGETPLATFORM
ARG TARGETARCH

RUN echo "target=${TARGETPLATFORM} arch=${TARGETARCH}"

Переменные TARGETPLATFORM и TARGETARCH относятся к целевой платформе, а не обязательно к архитектуре машины, на которой выполняется сборка. Их назначение и ограничения описаны в документации Docker о переменных сборки.

Пример сборки двух вариантов:

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t registry.example.org/research/pipeline:2026 \
  --push .

В реальном проекте замените адрес реестра на используемый лабораторией. После публикации снова проверьте манифест:

docker buildx imagetools inspect \
  registry.example.org/research/pipeline:2026

Для каждого варианта выполните один и тот же обезличенный тест. Зафиксируйте:

  • digest образа;
  • базовый образ и его digest;
  • версии Python, R, Java и системных библиотек;
  • параметры сборки;
  • входной набор;
  • контрольные результаты;
  • дату и платформу запуска.

Не объединяйте варианты только ради красивого тега. Если arm64 выдаёт другой результат из-за численной библиотеки или недоступного ускорителя, сохраните двойной маршрут и объясните его в документации проекта.

Сравните три стратегии перед выбором среды

Вариант Когда выбирать Сильные стороны Ограничения
Нативный arm64 на Apple Silicon В образе есть arm64, а зависимости переносимы Меньше архитектурных слоёв, удобная проверка arm64 Непереносимые x86-компоненты не заработают
amd64 через эмуляцию Нужно быстро проверить старый образ или воспроизвести короткий тест Не требуется немедленно менять Dockerfile Возможны ошибки нативных библиотек, медленная сборка и непригодность для тяжёлого расчёта
Нативный x86-узел Есть закрытые x86-бинарники, специфические драйверы или чувствительный расчёт Максимально близко к исходной среде авторов Нужен отдельный ресурс и отдельный контроль окружения
Двойная схема Проект должен поддерживать старый pipeline и новый Mac Меньше риска при миграции, проще сравнивать результаты Нужно вести два digest и два набора тестов

Сценарий из лабораторной практики

Представьте, что автор статьи передал образ с единственным linux/amd64. На Mac контейнер запускается, но модуль анализа падает при импорте. В этом случае не следует сразу обвинять Rosetta. Сначала выясните, какой .so или исполняемый файл загружается, затем проверьте, существует ли arm64-версия зависимости.

Если компонент закрытый и доступен только для x86, остановите принудительную миграцию. Используйте Mac для проверки пользовательского интерфейса, arm64-ветки или подготовительных этапов, а сам расчёт оставьте на x86. Если arm64-замена существует, соберите минимальный вариант и сравните результат на одном наборе данных.

Частые ошибки и безопасный порядок действий

Не смешивайте следующие утверждения:

  • «контейнер запущен»;
  • «entrypoint выполнен»;
  • «научная программа завершилась»;
  • «результат сопоставим с исходным».

Рабочий порядок выглядит так:

  1. Сохраните тег, digest и команду запуска.
  2. Определите архитектуру хоста через uname -m.
  3. Просмотрите платформы в манифесте через docker buildx imagetools inspect.
  4. Запустите arm64-вариант без эмуляции, если он доступен.
  5. Для amd64 включите --platform=linux/amd64 только как диагностический эксперимент.
  6. Проверьте entrypoint, основной бинарник и нативные расширения.
  7. Выполните минимальный научный тест с сохранением журналов.
  8. Если зависимость переносима, подготовьте multi-arch-сборку.
  9. Если зависимость x86-only, закрепите нативный x86-узел.
  10. В финальной документации укажите digest, платформу и представительский результат.

Не превращайте исправление в бесконечную переустановку. Каждый новый пакет меняет среду и затрудняет сравнение с опубликованным образом.

FAQ: что проверить в конкретной ситуации

Ответы ниже отделяют техническую возможность запуска от пригодности для научной эксплуатации. Это особенно важно, если вы переносите pipeline из лаборатории без полного доступа к исходному Dockerfile.

Почему Apple Silicon показывает несовпадение платформы?

Потому что Mac работает на arm64, а выбранный образ — на amd64, либо Docker не нашёл подходящий вариант в манифесте. Такое предупреждение не доказывает немедленный отказ и не подтверждает корректность эмуляции. Проверьте список платформ, затем сравните нативный запуск, диагностический amd64-запуск и реальный результат анализа.

Можно ли запускать только amd64-образ на Mac серии M?

Да, если доступна рабочая эмуляция. Но это компромисс, а не универсальный способ миграции. Старый образ может стартовать и всё равно падать на нативном расширении или выдавать непроверенный результат. Для краткой проверки используйте явный --platform=linux/amd64; для постоянной работы выбирайте multi-arch или x86-узел.

Что делать при exec format error?

Не начинайте с повторной установки Docker Desktop. Сначала определите entrypoint, проблемный файл и архитектуру каждого слоя. Проверьте команду запуска, оболочку и нативные расширения. Если ошибка вызвана x86-бинарником внутри arm64-варианта, найдите замену или верните задачу на x86. Успешный запуск оболочки ещё не означает исправность pipeline.

Как подготовить один образ для amd64 и arm64?

Сделайте зависимости архитектурно нейтральными, уберите безусловные x86-ссылки и собирайте через Docker Buildx с двумя целевыми платформами. TARGETARCH используйте только там, где действительно нужно выбрать архив или пакет. После публикации проверяйте манифест и гоняйте одинаковый набор данных на обеих архитектурах.

Достаточно ли Rosetta для любой проблемы amd64?

Нет. Rosetta касается перевода инструкций, но не исправляет несовместимые библиотеки, отсутствующие драйверы, ошибки Dockerfile или различия виртуального backend. Кроме того, возможности ускорения зависят от выбранного механизма виртуализации. Рассматривайте Rosetta как часть временной диагностической цепочки, а не как гарантию исследовательской воспроизводимости.

Когда выбрать Mac, x86 или двойной контур

Apple Silicon Mac подходит для проверки arm64-образа, macOS-зависимых инструментов, клиентского сценария и кроссплатформенной поставки. Он также удобен, когда вам нужно быстро выяснить, переносим ли pipeline на arm64, не покупая отдельную рабочую станцию.

Нативный x86-узел остаётся правильным выбором, если:

  • поставщик даёт только x86_64-библиотеку;
  • внутри pipeline используются закрытые бинарные модули;
  • расчёт чувствителен к различиям нативных библиотек;
  • эмуляция делает сборку или тестирование непредсказуемыми;
  • публикация должна совпадать с исходной средой авторов.

Двойной контур оправдан, если лаборатория одновременно поддерживает старые статьи и новые arm64-компьютеры. В таком случае не используйте один изменяемый тег как единственный источник истины. Храните digest, платформу, commit Dockerfile и representative output для каждой ветки.

Если вам нужно сначала проверить arm64-маршрут без покупки отдельного устройства, можно рассмотреть удалённый Mac для кроссплатформенной проверки. Такой ресурс полезен для короткого теста образа, сборки и результата, но не отменяет требования к нативному x86 для непереносимых вычислений. Перед началом работы проверьте также условия оформления аренды Mac.

Ваш текущий вариант — локальный Mac только с amd64-эмуляцией — имеет три реальных недостатка: он добавляет слой виртуализации, усложняет диагностику нативных библиотек и может не соответствовать среде, в которой авторы получили исходный результат. Если нужен временный arm64-тест, удалённый доступ к настоящему Apple Silicon Mac через MACCOME позволит проверить образ, зависимости и выходные файлы без немедленной покупки оборудования. Но если pipeline требует x86-only-компонентов или длительного тяжёлого расчёта, разумнее сохранить отдельный нативный x86-ресурс, а аренду Mac использовать именно как этап совместимости и приёмки.