Образ Docker, созданный на Mac OSX, не будет запускаться в экземпляре AWS EC2

#macos #docker #amazon-ec2 #apple-m1 #apple-silicon

#macos #docker #amazon-ec2 #apple-m1 #apple-silicon

Вопрос:

Изображение, созданное на Mac OSX с процессором M1, развернуто в экземпляре EC2. Но при запуске скриптов он выдает ошибку:

standard_init_linux.go:219: exec user process caused: exec format error

В другом месте Stackoverflow это объясняется несоответствием архитектуры ОС. Конечно, запуск «uname -m» на экземпляре EC2 показывает, что это x86_64, а «проверка образа docker» показывает, что контейнер имеет архитектуру arm64.

Вот чего я не понимаю. «uname -m» на моем Mac показывает, что это тоже x86_64. Итак, как контейнер наследует другую архитектуру?

Что еще более важно, как мне создать образ на моем Mac, который я могу запустить на EC2?

Файл Docker — это просто

 FROM python
WORKDIR /
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY src /src
 

с src, содержащим в настоящее время несколько простых скриптов на python, выполняемых таким образом:

docker run container/name python test.py

Это прекрасно работает на моем Mac, но выдает ошибку, указанную выше, при выполнении в AWS.

Ответ №1:

ОК. Вот что происходит. На моем Mac установлен новый чип M1, и я запускаю предварительную версию Docker Desktop. Под капотом чип имеет архитектуру arm64, но при опросе его через iTerm и VSCode он утверждает, что вместо этого он является x86_64, отсюда и мое замешательство, когда я опубликовал вопрос. Вероятно, это связано с тем, что оба эти приложения незаметно запускаются через симулятор Intel за кулисами, и это то, что реагирует на команду uname.

Однако, поскольку процессор на самом деле arm64, это базовая архитектура, когда я извлекаю изображения Python из Docker (я пробовал много разных вариантов и версий Python — все с одинаковыми результатами).

Чтобы принудительно использовать изображение, совместимое с amd64 AWS, я изменил первую строку Dockerfile на:

FROM --platform=linux/x86-64 python .

Когда контейнеры из этого образа запускаются на компьютере Mac, это вызывает предупреждение

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

но это всего лишь предупреждение, и скрипт запускается (предположительно, путем перенаправления обратно через симулятор Intel. Скрипты теперь выполняются без проблем (или предупреждений) на экземпляре EC2.

Комментарии:

1. Я должен буду иметь это в виду — это обязательно будет всплывать все чаще и чаще в будущем, хороший ответ!

2. Вы также можете использовать buildx для принудительного создания образов для разных платформ docker.com/blog/multi-platform-docker-builds

Ответ №2:

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

  1. Разместите свой код на github.
  2. Настройте репозиторий на hub.docker.com для вашего изображения и настройки автоматической сборки с github
  3. подключитесь по ssh к вашему экземпляру ec2 и извлеките свой образ непосредственно из docker hub

Альтернативный вариант — начать с шага 1, затем войти в свой ec2 с помощью ssh и клонировать репозиторий на этом компьютере. Затем вы можете создать его непосредственно на реальном компьютере с Linux (на вашем компьютере с osx не работает Linux, что является мгновенным несоответствием с docker). Если вы создадите его на сервере, вы сможете запустить его там без проблем.

Комментарии:

1. Это тестирование пути с целью переноса клиентской работы на Docker, поэтому общедоступные изображения на самом деле не вариант. Некоторые образы будут упакованы в контейнеры и отправлены на несколько серверов, поэтому создание образа на каждом сервере в данном случае тоже не работает. Тем не менее, информация об автоматических сборках из github интересна и может быть в другом месте. Большое спасибо, что обратили на это мое внимание.

2. Кстати, вы также можете использовать частные репозитории — вам не обязательно оставлять их открытыми для публики. Это стандартный шаблон, которому вы должны следовать, если используете более одного сервера. Это, безусловно, самый простой из всех вариантов. Вы даже можете использовать более ограниченный реестр, например собственный ECR Amazon. В конечном счете, если вы делаете это для парка серверов, вам также следует использовать kubernetes — это сложно, но это самый простой способ заставить все это работать вместе и поддерживать кластер серверов.

Ответ №3:

Попробуйте запустить с CMD ["lscpu"] или с чем-то связанным, например cat /proc/cpuinfo , в контейнере, сравните архитектуры

Еще одна вещь: возможно, вы используете arm архитектуру образа python при сборке и пытаетесь запустить его на x86_64 (EC2)

Комментарии:

1. docker image inspect | grep Architecture также предоставляет эту информацию без необходимости вводить код в изображение. Однако вы правы, речь шла о том, чтобы извлекать изображения с неправильной архитектурой, и ваш ответ вдохновил меня копнуть глубже и разобраться в этом.

Ответ №4:

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

По сути, последние версии Docker поставляются с командой CLI под названием buildx. Вы можете использовать команду buildx в Docker Desktop для Mac и Windows, чтобы создавать многоархивные образы, связывать их вместе с файлом манифеста и помещать их все в реестр с помощью одной команды.

Вот что работает для меня:

Создайте новый конструктор, который предоставляет доступ к новым функциям мультиархитектуры.

 docker buildx create --name mybuilder --use
 

Создайте файл Dockerfile с помощью buildx, передав список архитектур для сборки:

  docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t username/demo:latest --push .
 => pushing layers                                                             2.7s
 => pushing manifest for docker.io/username/demo:latest                       2.2
 

Где username — это допустимое имя пользователя Docker.

Примечания: Флаг —platform сообщает buildx о необходимости создания образов Linux для 64-разрядных архитектур AMD, 64-разрядных архитектур Arm и Armv7.
Флаг —push генерирует многоархивный манифест и отправляет все изображения в Docker Hub.

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

 docker buildx imagetools inspect username/demo:latest