Я Александр Калинка из компании Evrone. Мы работаем удалённо с 2008 года и делаем это на собственных устройствах. Иногда возникает проблема, как установить, настроить и запустить все приложения и сервисы, необходимые для использования в проекте. Кто‑то идет классическим путем, ставит необходимое локально на компьютер и работает с этим стеком. Но есть определенная часть программистов (и, несомненно, проектов), которые для развертывания необходимого зоопарка приложений используют Docker и Docker Compose. Устройства бывают разные, но особенно популярны Apple на чипсете M1 2020 года и на чипсете M2 2022 года. Работа Docker на них имеет некоторые особенности, о которых я хотел бы рассказать.
Сравнение работы Docker на Linux и Apple M1
Для начала остановимся на том, как работает Docker в родной Linux, и потом сравнить, как работает докер на MacOS устройстве с чипсетом М1, M2 и на Intel‑чипсете.
Служба Docker — это основной компонент Docker в Linux. Он работает как фоновый процесс и управляет контейнерами, образами и сетевыми соединениями между ними. Служба Docker работает внутри операционной системы, в свою очередь операционная система работает на базе ядра определенной версии и все это использует ресурсы физического процессора. Обычно это процессор с x86 или x64 архитектурой. Пользователь со своей стороны управляет работой Docker с помощью какого‑то клиента, обычно это The Docker CLI.
Допустим, пользователю для работы нужно использовать некий образ, скажем, Fedora. Что происходит когда пользователь выполняет команду docker run fedora
?
Docker проверяет, доступен ли локально образ, указанный в команде
docker run
. Если нет, он попытается скачать его из удаленного репозитория, такого как Docker Hub.Docker создает новый контейнер на основе указанного образа. Это включает настройку пространства имен файловой системы, сетевого пространства имен и других механизмов изоляции.
Docker настраивает переменные среды контейнера, сетевые подключения и другие параметры конфигурации на основе аргументов, переданных команде
docker run
.Docker запускает процесс, указанный в точке входа или команде образа. Процесс выполняется внутри изолированной среды контейнера.
Docker постоянно отслеживает процесс контейнера и использование ресурсов контейнера. Если процесс контейнера завершится, Docker остановит контейнер и связанные с ним ресурсы.
Одним из основных различий между macOS и Linux является архитектура. MacOS использует проприетарную архитектуру с закрытым исходным кодом, а Linux использует модульную архитектуру с открытым исходным кодом. Это может затруднить запуск Docker в macOS, поскольку для этого требуется запустить виртуальную машину Linux (ВМ) внутри хоста macOS. Виртуальная машина Linux запускает механизм Docker, который отвечает за управление контейнерами, а macOS предоставляет пользовательский интерфейс и другие ресурсы.
Еще одно различие между macOS и Linux заключается в работе с сетью. В macOS используется другой сетевой стек, что может усложнить настройку и управление сетевыми подключениями между контейнерами и хостом.
Наконец, могут возникнуть проблемы совместимости с некоторыми функциями и инструментами, специфичными для Linux, поскольку MacOS не имеет такого же уровня поддержки технологий, специфичных для Linux. Например, некоторые специфичные для Linux команды или библиотеки могут быть недоступны в macOS, и вам может потребоваться установить дополнительное программное обеспечение или изменить приложение, чтобы оно работало должным образом.
Производительность
Сначала я хотел бы показать один небольшой фокус, который можно воспроизвести на Docker Desktop Apple M1, но не получится на обычной Linux системе.
Как видно, если явно не указать архитектуру процессора, Docker скачивает и запускает образ для архитектуры linux/arm64
(то есть, соответствующую архитектуре чипсета M1), но если указать другую архитектуру, отличную от архитектуры хост машины, Docker скачает и запустит образ нужной нам архитектуры.
Но если выполнить эти команды на нативной Linux, такой финт не получится из-за другого способа запуска контейнеров.
На чипсете M1 фокус становится возможным, потому что Docker работает, используя виртуальную машину. Виртуальная машина замедляет выполнение контейнера, что несложно продемонстрировать с помощью бенчмарка на Golang.
Итак, у нас есть основной файл программы:
И файл теста для этой программы:
Запустив этот тест в контейнерах с основной и эмулируемой архитектурой, мы увидим следующие результаты:
QEMU
Для поддержки нового чипа M1 Docker использовал эмулятор QEMU с открытым исходным кодом (теперь Apple Virtualization Framework, но архитектурно ничего не поменялось). Эмулятор позволяет Docker запускать контейнеры на чипе M1, несмотря на то, что контейнеры были созданы для разных архитектур. QEMU — это универсальный эмулятор, который может имитировать широкий спектр аппаратных и программных сред. В случае с Docker на компьютерах M1 Mac QEMU используется для эмуляции архитектуры x86_64, для которой создано большинство контейнеров.
Использование QEMU таким образом позволяет Docker обеспечивать поддержку чипа M1 без необходимости перестраивать все существующие контейнеры для новой архитектуры. Это экономит много времени и усилий и позволяет пользователям продолжать использовать свои существующие контейнеры.
Помимо использования QEMU для поддержки чипа M1, Docker также использует технологию, называемую «мультиплатформенными образами», для дальнейшего улучшения совместимости контейнеров на компьютерах Mac M1. Эта технология позволяет пользователям создавать контейнеры, которые могут работать на нескольких архитектурах, включая x86_64 и новый чип M1.
Но QEMU это виртуальная машина, которая эмулирует компьютер целиком, и, надо сказать, использует для этого немало памяти. На скриншоте ниже вы можете видеть диспетчер задач сразу после старта Docker Desktop на MacBook M1 с 64 Гб оперативной памяти. Как видно, процесс виртуальной машины в конфигурации по умолчанию откусил от оперативной памяти около 8,5Гб.
Особенности работы QEMU на M1
QEMU (Quick EMUlator) — широко используемое программное обеспечение с открытым исходным кодом, позволяющее запускать приложения, разработанные для одной архитектуры, на другой архитектуре. Он использует двоичную трансляцию для преобразования машинного кода одной архитектуры в машинный код, который может выполняться другой архитектурой.
Binfmt_misc — это механизм ядра Linux, который позволяет регистрировать и использовать пользовательские двоичные форматы. Он работает, просматривая двоичный файл и выбирая подходящий интерпретатор для его выполнения, например QEMU для двоичного файла чужой архитектуры.
Когда вы запускаете двоичный файл внешней архитектуры на хост‑системе с включенной поддержкой QEMU и binfmt_misc, выполняются следующие шаги:
Ядро использует механизм binfmt_misc для проверки двоичного файла и определения его формата.
Binfmt_misc выбирает подходящий интерпретатор для выполнения бинарного файла, в данном случае QEMU.
QEMU запускается и начинает транслировать машинный код бинарника чужой архитектуры в машинный код, который может выполняться хостовой архитектурой.
QEMU использует двоичный перевод для перевода машинного кода чужой архитектуры в машинный код, который может выполняться хост‑архитектурой. Этот процесс происходит в режиме реального времени по мере выполнения двоичного файла.
Переведенный машинный код выполняется архитектурой хоста.
Новая версия Docker Desktop v4.6.0 (14 марта 2022 г.)
В Docker Desktop начиная с версии 4.6.0 пользователь может переключиться на использование virtualization.framework вместо hypervisor.framework.
После того как пользователь в настройках активирует изменения, в диспетчере задач тоже можно заметить некоторые изменения.
Вместо виртуальной машины QEMU появится новый процесс, который потребляет меньше ресурсов. И посмотрим на производительность в бенчмарке, который проводился для виртуальной машины QEMU.
Заметно некоторое ускорение работы, но все равно медленнее, чем на родной Linux.
Плюсы использования virtualization.framework:
Простота: virtualization.framework предоставляет простой и удобный в использовании API для создания и управления виртуальными машинами, что может быть преимуществом для разработчиков, плохо знакомых с виртуализацией.
Интеграция с экосистемой macOS: virtualization.framework является частью операционной системы macOS, что означает, что он может использовать базовые аппаратные и программные компоненты для предоставления высокопроизводительного решения виртуализации.
Портативность: virtualization.framework предназначен для переноса между различными версиями macOS и аппаратными платформами, что может сделать его хорошим выбором для решений виртуализации, которые должны работать на разных системах macOS.
Минусы использования virtualization.framework:
Ограничения: у virtualization.framework есть некоторые ограничения с точки зрения поддерживаемых функций и обеспечиваемой производительности по сравнению с другими технологиями виртуализации. Например, он может не поддерживать все функции полноценного решения для виртуализации, а его производительность может быть ограничена базовыми аппаратными и программными компонентами.
Отсутствие кросс-платформенной совместимости: virtualization.framework ограничен операционной системой macOS, а это означает, что решения для виртуализации, созданные с его помощью, нельзя легко переносить на другие операционные системы или аппаратные платформы.
Следует ли использовать virtualization.framework или hypervisor.framework, зависит от ваших конкретных требований и потребностей.
Также пользователь может активировать использование VirtioFS для обмена файлами. Плюсы такого решения:
Производительность: VirtioFS обеспечивает высокопроизводительный доступ к файловой системе в виртуализированной среде, что может повысить производительность приложений, работающих в контейнере Docker.
Простота использования: VirtioFS разработан так, чтобы его было легко использовать, а процесс настройки и настройки несложный. Это может сделать его хорошим выбором для пользователей, которые плохо знакомы с виртуализацией и Docker.
Межплатформенная совместимость: VirtioFS совместима с разными платформами, что означает, что ее можно использовать с различными технологиями виртуализации и операционными системами. Это делает его хорошим выбором для пользователей, которым необходимо запускать контейнеры на разных платформах.
Но существуют и минусы:
Сложность: VirtioFS — относительно новая технология, и ее установка и настройка может быть более сложной, чем другие технологии виртуализации.
Ограничения: VirtioFS имеет некоторые ограничения с точки зрения поддерживаемых функций и обеспечиваемой производительности. Например, он может не поддерживать все функции полноценной файловой системы, а его производительность может быть ограничена технологией виртуализации, с которой он используется.
Заключение
Хотя Docker может работать в macOS, существуют некоторые различия в том, как Docker работает в macOS и Linux, которые могут повлиять на производительность и совместимость. Если вы хотите использовать Docker в macOS, важно знать об этих различиях и понимать потенциальные ограничения и проблемы, с которыми вы можете столкнуться.