Инструкции

Docker на Apple Silicon: exec format error и как с этим жить

Docker на Apple Silicon: exec format error и как с этим жить

Docker на Apple Silicon: exec format error и как с этим жить

Если вы разработчик, переехали с Intel Mac на Apple Silicon, и Docker Desktop внезапно перестал запускать ваши привычные образы - с ошибкой вроде этой:

exec /usr/local/bin/entrypoint.sh: exec format error

Или так:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8)

Это нормально. Ваш новый Mac работает на ARM архитектуре, а Docker образы которыми вы пользуетесь годами собраны под x86_64 (amd64). Разница фундаментальная, и просто так это не пройдёт. Рассказываю что происходит и как правильно работать с Docker на Apple Silicon.

Почему ошибка exec format error

На низком уровне процессор выполняет инструкции на своём конкретном языке. ARM процессоры и Intel/AMD процессоры говорят на разных языках. Программы собранные под x86 - это файлы с инструкциями для Intel процессора. ARM процессор их физически не может выполнить.

Когда Docker пытается запустить amd64 контейнер на ARM хосте:

  1. Контейнер "распаковывается"
  2. Docker пытается запустить entrypoint бинарник (обычно это /bin/sh или /usr/local/bin/entrypoint.sh)
  3. Ядро Linux внутри контейнера видит заголовок ELF файла - там указана архитектура x86_64
  4. Архитектура не совпадает с хостом arm64
  5. Ядро возвращает ENOEXEC - "exec format error"
  6. Контейнер падает без объяснений

На Intel Mac такой проблемы никогда не было, потому что Intel Mac и amd64 образы говорят на одном языке.

Решение 1: используйте multi-arch образы

Большинство официальных Docker образов уже имеют версии под обе архитектуры. Например:

  • nginx:latest - есть и amd64, и arm64 версии
  • postgres:16 - есть обе
  • redis:7 - есть обе
  • node:20 - есть обе
  • python:3.12 - есть обе

Когда вы делаете docker pull nginx:latest на Apple Silicon, Docker автоматически скачивает arm64 версию. Никаких проблем не будет.

Проверить поддерживает ли образ вашу архитектуру:

docker manifest inspect nginx:latest | grep architecture

Увидите что-то вроде:

"architecture": "amd64"
"architecture": "arm64"
"architecture": "arm/v7"

Если есть arm64 - всё хорошо, просто используйте образ как обычно.

Решение 2: --platform linux/amd64

Если образ только для amd64 (нет arm64 версии), и у вас нет возможности пересобрать его под ARM, используйте эмуляцию через флаг --platform linux/amd64:

docker run --platform linux/amd64 некоторый-amd64-образ

Docker Desktop на Apple Silicon имеет встроенную эмуляцию x86 через Rosetta 2 или QEMU (в зависимости от версии Docker Desktop и настроек). С флагом --platform linux/amd64 он будет транслировать инструкции x86 в ARM64 на лету.

Минусы эмуляции:

  • Производительность в 2-5 раз хуже чем нативная
  • Больше потребление CPU и батареи
  • Иногда сегфолты в сложных программах
  • Не все образы работают - например, некоторые программы на Haskell или Rust с нестандартными зависимостями
  • Запускается медленно - загрузка образа занимает больше времени

Несмотря на минусы, --platform linux/amd64 работает для 90% программ и позволяет запускать amd64-only образы без проблем.

Решение 3: включите Rosetta для Docker

В Docker Desktop 4.25+ появилась опция использовать Rosetta 2 вместо QEMU для эмуляции x86. Rosetta значительно быстрее QEMU (иногда в 2-3 раза).

Как включить:

  1. Откройте Docker Desktop
  2. Зайдите в Settings (шестерёнка)
  3. General - включите "Use Virtualization framework"
  4. Features in development - включите "Use Rosetta for x86/amd64 emulation on Apple Silicon"
  5. Apply & Restart Docker

После этого --platform linux/amd64 будет использовать Rosetta 2 вместо QEMU. Работает заметно быстрее.

Требования:
- macOS Ventura 13.3 или новее
- Docker Desktop 4.25.0 или новее
- Apple Silicon Mac (M1/M2/M3/M4)

Если у вас Docker Desktop старый - обновите его.

Решение 4: docker buildx для мультиархитектурных сборок

Если вы сами собираете образы (например, Dockerfile в вашем проекте), используйте buildx для сборки сразу под несколько архитектур:

docker buildx create --name multiarch --use
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest --push .

Эта команда соберёт образ и под amd64, и под arm64, и запушит в registry. Разработчики на Intel будут скачивать amd64 версию, на Apple Silicon - arm64. Всё работает нативно, никакой эмуляции.

Для сборки:
- Запись --push обязательна (buildx не создаёт локальный образ при multi-arch сборке)
- Требуется зарегистрированный репозиторий Docker Hub или другой registry
- Сборка займёт в 2 раза больше времени (и время места)

Это правильный способ распространять ваши образы в 2026 году. Не заставляйте пользователей мучиться с эмуляцией.

Решение 5: docker-compose.yml - настройка платформы

Если используете docker-compose, добавьте platform в определение сервиса:

services:
  mysql:
    image: mysql:8
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: secret
    ports:
      - "3306:3306"

Или ещё лучше - используйте образы с поддержкой multi-arch:

services:
  db:
    image: postgres:16        # уже multi-arch, ничего не надо
    environment:
      POSTGRES_PASSWORD: secret

Что НЕ работает через эмуляцию

Некоторые программы не запускаются даже через Rosetta/QEMU на Apple Silicon:

  • Специфичные AVX512 инструкции - современные Intel процессоры, отсутствуют на M1/M2, иногда и Rosetta не помогает
  • Некоторые версии Oracle Database - тонкости работы с памятью
  • Старые версии Java (до 8) - используют устаревшие syscalls
  • Проприетарные закрытые бинарники без ARM версии

Если столкнулись с одним из этих случаев - альтернативы:

  1. Облачный Docker host на AWS/DigitalOcean с Intel процессором через SSH туннель
  2. VM с Ubuntu x86 в UTM или Parallels, Docker внутри неё
  3. Переписать код на что-то более портативное

Как проверить архитектуру запущенного контейнера

Сомневаетесь что запускается? Проверьте внутри контейнера:

docker run --rm nginx:latest uname -m

Вывод:
- x86_64 - запустился как amd64 (через эмуляцию если Mac на ARM)
- aarch64 - запустился нативно под ARM

Также можно посмотреть список запущенных контейнеров с указанием платформы:

docker ps --format "table {{.Names}}\t{{.Image}}"
docker inspect <container-id> | grep -i architecture

Troubleshooting частых проблем

Мой приложение работает на Intel, но падает на Mac M1 даже с --platform linux/amd64

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

  1. Обновить Docker Desktop до последней версии
  2. Включить Rosetta в настройках (см. выше)
  3. Поискать ARM версию вашей программы
  4. Если ничего не помогло - запустить в облаке

"no matching manifest for linux/arm64/v8 in the manifest list entries"

Образ вообще не имеет ARM версии. Варианты:

  • Использовать --platform linux/amd64 (эмуляция)
  • Найти альтернативный образ с ARM поддержкой
  • Собрать свой образ из исходников

Docker Desktop очень медленно работает на M1 8GB RAM

Уменьшите выделенную Docker RAM в настройках. 4-5 GB обычно хватает для небольших проектов. Чем меньше - тем меньше свопинга системы.

x86_64 контейнер запускается, но внутри программа зависает

Проблема с многопоточностью в Rosetta. Попробуйте:
- Ограничить количество CPU для контейнера: docker run --cpus=2 ...
- Отключить Rosetta (использовать QEMU): снять галку в настройках Docker

Частые вопросы

Docker на M1 медленнее чем на Intel?
Для ARM образов - нет, часто быстрее. Для amd64 с эмуляцией - да, в 2-5 раз медленнее.

Нужна ли Rosetta 2 для Docker?
Для Docker Desktop 4.25+ с включённой опцией Rosetta - да. Если не хотите ставить Rosetta - используйте QEMU (будет медленнее).

Какой выбрать Docker Desktop или Docker через Homebrew?
Docker Desktop удобнее для большинства (GUI, автоматические обновления, встроенная VM). Homebrew установка (brew install docker) - только CLI, нужна отдельная VM через colima или docker-machine.

Что такое Colima и нужна ли она?
Colima - альтернатива Docker Desktop, open source, без лицензионных ограничений. Для коммерческой разработки в компаниях >250 сотрудников Docker Desktop требует платной лицензии, Colima бесплатна.

Kubernetes на M1 работает?
Да, minikube и kind работают отлично. Некоторые helm chart'ы используют amd64-only образы - добавляйте --platform linux/amd64.

Как избежать --platform linux/amd64 в будущем?
Используйте только multi-arch образы (большинство популярных уже такие), и собирайте свои образы через docker buildx build --platform linux/amd64,linux/arm64.

Надеюсь теперь понятно почему Docker ругается и как с этим правильно работать. Apple Silicon это лучшая платформа для Docker разработки - быстрая, энергоэффективная, и большинство образов уже мультиархитектурные.

Комментарии (0)

Пока нет комментариев.