Привет, Хабр! Меня зовут Ярослав, я стажер инженерно-технического отдела в Selectel. В своих пет-проектах уже давно использую роутеры MikroTik. Но я никогда думал, что на них станет возможным развернуть Docker. Релиз стабильной версии RouterOS 7.5 изменил мое мнение: теперь MikroTik поддерживает контейнеризацию.

На примере Nextcloud показываю, как установить и настроить приложение в контейнере, и рассказываю, с какими ограничениями можно столкнуться. Подробности под катом.

Начнем с ограничений


Не каждый MikroTik поддерживает контейнеры


К сожалению, функционал поддерживается не на всех роутерах. Контейнер можно запустить только на устройстве с архитектурой ARM, ARM64 или x86. Из беспроводных роутеров можно использовать MikroTik линейки Chateau и некоторые hAP-модели. Из проводных — RB1100AHx4 Dude Edition, RB3011 и RB5009. А также — новые роутеры линейки CCR (CCR2004-16G-2S+, CCR2116-12G-4S+, CCR2216-1G-12XS-2XQ).

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

Архитектуру x86 поддерживают программные роутеры CHR, которые могут быть установлены на сервер или виртуальную машину с соответствующим процессором.

Если у вас есть сервер, можно установить на него любую систему виртуализации создать несколько виртуальных машин. На одной из них — развернуть образ программного роутера CHR Mikrotik, а на другой — серверную операционную систему с Docker или нужным ПО.

В этом случае нет необходимости ставить контейнеры внутрь RouterOS. На мой взгляд этот способ является более стабильным и функциональным решением. Но есть одна особенность: установить контейнер RouterOS может быть быстрее, чем разворачивать систему виртуализации. К тому же она может потребовать дополнительного лицензирования.

Если вы знаете, для чего может понадобиться контейнеризации на CHR, поделитесь опытом в комментариях.

Контейнер ограничен характеристиками роутера


У аппаратных роутеров достаточно жесткие ограничения по оперативной памяти. Объем ОЗУ на роутерах, за исключением линейки CCR, не превышает 1 ГБ. И если, например, половину объема оставить под нужды RouterOS, контейнер с приложением будут сильно ограничены в памяти.

С ресурсами процессора ситуация не лучше. Для примера: приложение Nextcloud, которое я развернул на роутере RB3011, загрузило оба ядра на 100% — и это без какой-либо нагрузки.


Окно Resources, состояние процессорных ядер.

Также можно столкнуться с ограничениями по объему памяти флеш-накопителя. Его вместимость не превышает 128 МБ, за исключением накопителя в роутере RB5009. Поэтому память лучше оставить исключительно для хранения конфигураций. А для работы контейнера и хранения примонтированных каталогов использовать внешний накопитель.

Некоторые модели имеют SATA- и M.2-разъемы для подключения внешних накопителей. Если таких разъемов нет, можно воспользоваться USB и подключить флешку.

Риски использования


Немаловажна и безопасность: нужно понимать, что, если роутер будет скомпрометирован, злоумышленники могут загрузить любое вредоносное ПО в контейнере. Это может привести к чему угодно, если роутер включен в домашнюю или корпоративную сеть.

Подробнее со всеми рисками можно ознакомиться на официальном сайте.

MikroTik снимает с себя ответственность за безопасность RouterOS с установленными контейнерами. Поэтому нужно быть уверенным, что используемое ПО не содержит уязвимостей.


Подготовка роутера к установке контейнеров


Я уже говорил, что к аппаратному роутеру нужно подключить дополнительный накопитель. Кроме того, нужно обновить систему RouterOS до stable-версии 7.5 или выше, а потом — RouterBOARD. Но это не все, что понадобится.

Каждый из последующих этапов можно выполнить через графический интерфейс RouterOS или командную строку.

Форматирование диска


Предварительно нужно отформатировать накопитель для работы с файловой системой ext3/ext4: нужно выбрать новый накопитель и нажать Format Drive.


Окно Format Drive, настройка форматирования диска.

/disk/print 

Flags: M, r - RAID-MEMBER; p - PARTITION
Columns: SLOT, MODEL, SERIAL, INTERFACE, NAME
#    SLOT        MODEL                         SERIAL                INTERFACE         NAME 
0    usb1        JetFlash Mass Storage Device  CCYYMMDDHHmmSSECGXE8  USB 2.10 480Mbps       
1 Mp usb1-part1
     
/disk/format-drive usb1 file-system=ext4

Настройка форматирования диска.
usb1 — имя накопителя, полученное командой /disk/print


Установка дополнительного пакета для работы с контейнерами


На официальном сайте в разделе Software нужно найти блок с архитектурой процессора используемого роутера. А после — скачать архив Extra packages. В нем должен быть файл container, который нужно переместить в Winbox, в окно File.


Содержание архива Extra packages.


Файловая система Winbox.

Для установки пакета необходимо перезагрузить роутер.

Активация функционала контейнеров


Последний этап подготовки — активация функционала контейнеров. В терминале RouterOS нужно ввести специальную команду.

/system/device-mode/update container=yes
update: please activate by turning power off or pressing reset or mode button in 4m53s
-- [Q quit|D dump|C-z pause]

После сообщения нужно в течение 5 минут перезагрузить роутер, то есть выключить и включить его по питанию, либо нажать на кнопку reset или mode.

Установка образа контейнера с Docker Hub


Создание виртуального сетевого интерфейса


В разделе Interface → VETH нужно создать виртуальный сетевой интерфейс для будущего контейнера. Для этого нужно настроить несколько параметров:
  • Name — название сетевого интерфейса,
  • Address — IP-адрес и битовая маска подсети для контейнера. По данному адресу можно будет подключиться к контейнеру,
  • Gateway — IP-адрес, который контейнер будет использовать в качестве шлюза для работы с устройствами в других подсетях.

Окно VETH, создание виртуального сетевого интерфейса.

/interface/veth/add name=veth3 address=10.10.4.4/24 gateway=10.10.4.1

Создание виртуального сетевого интерфейса VETH.

Для включения контейнера в сеть можно создать «виртуальный коммутатор» bridge, назначить ему IP-адрес и добавить в него виртуальный интерфейс.
/interface/bridge/add name=container-bridge
/ip/address/add address=10.10.4.1/24 interface=container-bridge
/interface/bridge/port/add bridge=container-bridge interface=veth3

Создание виртуального коммутатора для контейнеров и его настройка.

На самом деле, в bridge добавлять интерфейс не обязательно — его можно использовать отдельно, настроив, например, соединение point-to-point.

/interface/veth/add name=veth4 address=10.10.5.2/30 gateway=10.10.5.1
/ip/address/add address=10.10.5.1/30 interface=veth4

Назначение IP-адресов на PtP-интерфейс.

Я заметил особенность поведения RouterOS: при смене IP для виртуального сетевого интерфейса VETH, внутри самого контейнера адрес не обновляется. По поводу этой проблемы я создал тему на форуме MikroTik.

Конфигурирование контейнера


Далее нужно перейти в раздел Container → Config и настроить несколько параметров:
  • RAM Hight — опциональный параметр, ограничивает контейнеры в потреблении оперативной памяти,
  • Registry URL — адрес, с которого будет устанавливаться контейнер при запуске (для загрузки образа с Docker Hub нужно ввести registry-1.docker.io),
  • Tmp dir — путь до директории, куда будут перемещены временные файлы, необходимые для установки контейнера. Рекомендую располагать директорию на дополнительном накопителе (disk2).

Окно Config, конфигурирование контейнера.

/container/config/set ram-high=768M registry-url=https://registry-1.docker.io tmpdir=disk2/tmp

Конфигурирование контейнера через консоль.

Особенности конфигурирования


Во время работы с Container → Config нужно учитывать ряд особенностей:
  1. При заполнении RAM High через Winbox неочевидно, в каких единицах нужно вводить значение. Нельзя использовать упрощенную модель — например, 768M, когда буква обозначает единицу измерения (килобайты, мегабайты, гигабайты). Объем необходимо указывать в байтах. Хотя в терминале подобная запись работает.
  2. При установке контейнера в RouterOS все приложения из каталога монтирования — например, Nextcloud (/var/www/html) — отображаются сплошным списком, без соблюдения иерархии директорий. Это сильно затормаживает загрузку раздела File и вызывает неудобства в использовании. Например, после установки контейнера с Nextcloud в разделе File появляется около 46 000 строк, которые загружаются больше минуты.


  3. Вторая особенность вызывает неудобства и в работе с терминалом. Когда в системе содержится большое количество файлов, при настройке конфигурации контейнеров RouterOS не дает ввести путь до директории для временных файлов (tmpdir). Возможно, это происходит из-за долгой индексации файлов во время проверки системой вводимых команд.
Возможно, эти тексты тоже вас заинтересуют:

Домашний дата-центр: ошибки, результаты и советы
ML в Managed Kubernetes: для каких задач нужен кластер с GPU
Docker Swarm VS Kubernetes — как бизнес выбирает оркестраторы

Настройка и запуск контейнера с Nextcloud


После подготовки роутера можно создать и настроить контейнер с приложением.

Создание переменных для управления контейнером


Для управления будущим контейнером нужно создать специальные переменные. Они будут «пробрасываться» внутрь него и подгружать значения, например, в конфигурационных файлах.

Таких переменных может быть очень много. Поэтому их принято группировать. Для этого нужно перейти во вкладку Evns и заполнить форму из нескольких полей:
  • Name — название группы переменных,
  • Key — ключ,
  • Value — значение ключа.

Окно Env, добавление переменных.

/container/envs/add name=nextcloud_evns key=APACHE_LOG_DIR value=/var/log/httpd

Команда для добавления переменных

Группы переменных понадобятся во время создания контейнера.

Настройка каталога монтирования Nextcloud


В RouterOS есть вкладка Mounts — аналог атрибута --mount, который нужен для создания каталогов монтирования в традиционном Docker. С помощью Mounts можно сопоставить директории, находящиеся в файловой системе MikroTik, и директории, находящиеся внутри контейнера.

Это нужно сделать для тех директорий, которые важно не потерять в случае перезагрузки контейнера. В моем случае нужно было создать точку монтирования для директории Nextcloud (/var/www/html).

Чтобы это сделать, нужно указать специальные параметры:
  • Name — уникальное имя точки монтирования. Оно понадобится при создании контейнера,
  • Src — путь к директории, находящейся на внешнем накопителе, которую необходимо смонтировать,
  • Dst — путь к директории назначения внутри контейнера.

Окно Mount, добавление каталога монтирования.

/container/mounts/add name=nextcloud_html src=disk2/nextcloud_html dst=/var/www/html

Запуск контейнера


Наконец, можно создать и запустить контейнер. Для этого нужно перейти во вкладку Container и заполнить следующие поля:
  • Remote Image — название образа контейнера, который будет установлен (в моем случае с Docker Hub),
  • Interface — VETH-интерфейс для использования с контейнером,
  • Envlist — список переменных среды, настроенных в Container → Envs, которые будут использоваться контейнером,
  • Root Dir — директория, в которую будет установлен контейнер,
  • Mounts — точки монтирования, настроенные в Container → Mounts.

Окно Container, финальная настройка и запуск.

/container add remote-image=arm32v7/nextcloud:latest envlist=nextcloud_envs hostname=nextcloud interface=veth1 mounts=nextcloud_html root-dir=disk2/nextcloud

Команда для создания контейнера.

После можно запустить контейнер нажатием на кнопку Start. Или с помощью специальной команды.

/container/start number=1

/container/print

Запуск Nextcloud в Docker-контейнере.
1 — номер контейнера, который можно узнать командой /container/print



Стартовое окно Nextcloud.

Изначально в RouterOS 7.5 функция автозапуска контейнеров после перезагрузки роутера отсутствовала. В версии 7.6 такая возможность появилась, но она все еще недоступна для настройки через Winbox.

Если контейнер уже создан, добавить его в автозагрузку можно специальной командной через терминал.

/container/set 1 start-on-boot=yes

1 — номер контейнера

Если вы только создаете контейнер, то в команде нужно прописать специальный параметр.

start-on-boot=yes


Первые настройки всегда «комом»


В большинстве случаев контейнер запустить с первого раза не получится. Настройки, как блины, первый раз получаются «комом». Чтобы узнать, в каком месте допущена ошибка, вывод информации (исключений и ошибок) нужно транслировать из контейнера в log роутера.

Достаточно поставить галочку рядом с Logging.


Окно Container, включение логирования сообщений. В консоли для этого нужно выполнить команду /container/set 1 logging=yes

Или вручную подключиться к работающей оболочке контейнера. Для этого нужно ввести команду и номер контейнера.

[admin@R1] > /container/shell 1
root@wireguard:/# ls
bin   data  etc             home  media  opt   root  sbin  start.sh  tmp  var          web-vault
boot  dev   healthcheck.sh  lib   mnt    proc  run   srv   sys       usr  vaultwarden
root@wireguard:/# whoami
root
root@wireguard:/# exit
exit
done

Подключение к командной строке внутри контейнера, внутри которой можно выполнять любые команды (Is, whoami).

Оба способа помогут оперативно отловить «фичу» и прокричать «Ура, я запустил Docker на MikroTik!». Но оправдана ли радость?

Зачем вообще нужен контейнер на MikroTik?


Контейнеризация в MikroTik может быть полезна для решения нетребовательных задач, для которых не нужно поднимать отдельные серверы.

Вот несколько возможных сценариев использования «домашних контейнеров»:
  • Организация облачного файлового хранилища. Тут важно отметить, что лучше использовать приложения «попроще». Nextcloud слишком нагружает роутер.
  • Развертывание менеджера паролей. Повторюсь: лучше использовать менее нагрузочное ПО. Например, в качестве менеджера паролей вместо bitwarden можно установить его аналог — vaultwarden. Но помните: ответственность за безопасность паролей остается за вами.
  • Запуск полноценного DNS-сервера. Благодаря контейнерам на роутерах MikroTik стало возможным поднимать полноценные DNS-серверы и делегировать им управление доменами. Это можно сделать с помощью установки BIND 9. Именно этим я займусь во время апгрейда своего домашнего дата-центра, о котором можно почитать в блоге Selectel.

Область применения контейнеров на RouterOS ограничивается лишь вашей фантазией и… «железом» роутеров.

Из-за ресурсных ограничений контейнеры на MikroTik подходят не всегда. Для развертывания высоконагруженных сервисов лучше воспользоваться полноценным сервисом — например, Managed Kubernetes.

А какое приложение на MikroTik запустили бы вы? Поделитесь своим мнением в комментариях.

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


  1. kernelconf
    20.10.2022 17:26
    +4

    vlmcsd. Гораздо более уместно, нежели Nextcloud.


  1. denis-isaev
    20.10.2022 18:53
    +7

    Май гад! ) Следующим шагом ждем Дум на Микротике )


    1. anwender95
      21.10.2022 08:03
      +2

      кмк дум будет есть куда меньше ресурсов чем докер.


    1. Fullmoon
      21.10.2022 10:01

      Ну, например, https://github.com/CallumHoughton18/Doom-In-Docker. Baremetal будет посложнее, конечно.


  1. Greenback
    20.10.2022 19:30

    У меня RB951, который докер не потянет.

    Я воткнул в USB порт малютку Raspberry PI Zero W2, приклеив двусторонним скотчем. Он по USB и питание получает и сетевой интерфейс предоставляет. Настоящий компик с линуксом, без шаманства, бонусом WiFi и Bluetooth.

    Цена вопроса 15$


    1. Whyborn77
      20.10.2022 19:51

      уже с годик висит на моем ac3 в usb порту pi zero 2 и прекрасно себя чувствует (с дешевыми алиэкспресными медными радиаторами) и коллекция докера подтверждает надежность азиатской апельсинки:

      pihole

      homeassistant 

      watchtower

      portainer_edge_agent


    1. Doman
      21.10.2022 11:02

      К сожалению, RPI Z2 W уже несколько месяцев как не купить, а если где-то и всплывает, то за совсем другой прайс.


    1. yabovbel Автор
      21.10.2022 11:38

      Круто, сила инженерной мысли!


  1. Tabletko
    20.10.2022 19:54
    +1

    Почему-то не упомянули reverse proxy, которого так не хватало на микротике в малых инсталляциях.


  1. avelor
    20.10.2022 20:46

    Чуть игрался с этой темой при первом появлении в бете (7.1 какой-то). Забавное

    Не проверяли, контейнеры всё ещё непривелигированные? Хотел запустить контейнер с tap внутри (да, я странный), но --cap-add=NET_ADMIN опции как-то не было:)


    1. Whyborn77
      20.10.2022 20:47
      +2

      отвечу скрином с контейнера на chr


      1. avelor
        21.10.2022 00:31

        да, и вправду повеселее. но tap ведёт себя не очень адекватно:)


  1. JayK
    21.10.2022 06:33

    Вообще конечно оч интересно. Допустим если 4011 применяется дома или в небольшом офисе, то и памяти и места на диске там предостаточно, 5009 уж тем более. Вот сижу думаю что бы туда можно было закачать. Видится логичным такое применение для которого малинка (которая нынче несмешно стоит) это овермощь.

    Смысла в контейнере на CHR не вижу вообще никакого, CHR бай дизайн уже стоит в виртуальной среде.

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


  1. Abyss777
    21.10.2022 07:46

    Я бы туда поставил SQUID c kerberos авторизацией и фильтрацией HTTPS


  1. OptimumOption
    21.10.2022 07:47
    +1

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


    1. JayK
      21.10.2022 09:16

      просто домохозяйки долго просили микротик чтобы он качал торренты, ну и вот вам решение)


    1. DaemonGloom
      21.10.2022 10:02

      Условные pi-hole или какой-нибудь хитрый прокси/vpn проще поставить на роутер, поскольку это сервисы, прямо связанные с его работой. Понятно, что ставить туда Home Assistant — решение странное и потом принесёт кучу проблем.


      1. JayK
        21.10.2022 10:10

        выше пишут проблемы с тап адаптерами


        1. DaemonGloom
          21.10.2022 11:27

          Вроде, и tun, и tap работают с конца июля.


        1. avelor
          21.10.2022 12:20

          в целом я запроверил - есть нюансы, да. но работает.

          так под мою задачу изначальную проще и стабильнее перешить кротик в openwrt (заодно нужное собрать можно не только под arm\x86, но и под mips)


    1. avelor
      21.10.2022 12:21

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


  1. wiremein
    21.10.2022 11:29

    Давайте научим маршрутзаор варить кофе.


  1. Wernisag
    21.10.2022 13:38

    Очевидно, что для полноты не хватает двух вещей. Запуск дума и CHR через контейнер


    1. yabovbel Автор
      21.10.2022 21:51

      Запуск DOOM уже стал традицией)) а вот запустить CHR в контейнере на аппаратном роутере не удастся. Проблема в поддерживаемых архитектурах. CHR удастся запустить только на x86 системе, а аппаратных платформ у Mikrotik с такой архитектурой нет.