Вообще, Docker-контейнеры - довольно хороший и полезный инструмент: окружение, которое очень легко скачать, запустить, поломать и не волноваться на этот счёт - потому что новое такое же окружение запускается за секунды. Кроме того, в контейнере можно упаковать какую-то полезную утилиту, которая будет просто работать - вне зависимости от того, что там творится в хост-системе. Наконец, некоторые контейнеры позволяют быстро и просто что-то настроить в хост-системе!
В наше время много софта надо разрабатывать для arm-систем. При этом сами эти системы, как правило, не отличаются высокой производительностью, и какой-нибудь комп на x86_64 окажется гораздо ближе. Нормальная кросс-компиляция - давно утраченное искусство, людям гораздо проще принести в жертву девять десятых производительности, чем пытаться всё правильно настроить. Всех спасает qemu-user
(usermode-эмуляция другого процессора - очень проста в запуске) и binfmt_misc
(особенность ядра GNU/Linux, позволяющая запускать "интерпретаторы" для файлов автоматически).
Всё бы ничего, но qemu-user
(как бинарник) тогда надо тянуть в тот chroot, где хочется что-то запустить. Это особенно накладно в случае с контейнерами, "родная" архитектура - arm
, arm64
и прочее. Каждый раз создавать свой контейнер, который будет просто содержать дополнительно нужный бинарник qemu-user
накладно. Так как быть?
Решение - флаг F
для binfmt_misc
! Это позволяет зарегистрировать нужный интерпретатор так, чтобы он оставался в памяти (внимание: фишка работает с ядрами >=4.8, если кто-то будет это прикручивать к Travis'у - не забудьте поставить dist: bionic
).
Казалось бы, при чём тут докер?
А докер позволяет автоматизировать процесс регистрации binfmt_misc
. Я взял готовое решение, чуть допилил его, и теперь всем предлагаю запускать:
docker run --rm --privileged sfalexrog/qemu-register:v4.1.0
для регистрации qemu-user
в binfmt_misc
.
Кстати, оставшиеся контейнеры имеет смысл запускать после того, как этот отработает.
Иногда надо быстро посмотреть, как что-то сделано в дефолтном Raspbian'е, а Raspberry нет под рукой. Конечно, можно скачать образ, завести полноценный qemu
, а можно просто запустить тот контейнер, который был выше, а затем:
$ docker run -it --rm sfalexrog/raspbian:buster
root@93bcc3c835e6:/#
Вместо buster
можно написать stretch
- это приведёт ко вполне ожидаемому результату (будет запущен контейнер, основанный на stretch'е).
Особая сборочная магия находится здесь.
Раз уж OSRF выпускает свои контейнеры с ROS, то чем мы хуже? На данный момент есть только ROS Melodic, дальше (по мере появления собранных ROS'овских пакетов), возможно, ещё что-то добавится.
$ docker run -it --rm sfalexrog/rpi-ros:melodic-core
root@6c4278927475:/# echo $ROS_DISTRO
melodic
Сборка ROS-пакетов - задача build-ферм, и решена она была уже много раз. Поэтому у нас есть n+1-е решение для сборки ROS-пакетов!
Контейнер multipack
собирает все пакеты, которые найдёт в ROS workspace, и выплёвывает их (и некоторые дополнительные данные для rosdep
) в свой /output
. Вызывать этот котнейнер можно так:
$ docker run --rm -v $(pwd):/rosbuild/src -v ${HOME}/packages:/output sfalexrog/multipack:melodic
Ожидается, что в текущей директории будут находиться поддиректории с исходниками ROS-пакетов, а в ${HOME}/packages
будут складываться результаты сборки.
Посмотреть, как это устроено внутри, можно здесь.