Начиная с версии RouterOS 7 появилась возможность запускать Docker совместимые контейнеры прямо на роутерах MikroTik. В статье мы рассмотрим, про использование пакета Container на роутерах MikroTik, как включить поддержку контейнеров, настроить внешнее хранилище для контейнеров на подключенном USB диске, настройку сети для контейнеров, установку и управления образами.
Системные требования:
- Не каждый роутер MikroTik поддерживаем контейнеры. Проверяйте поддержку для вашей модели на сайте производителя.
- На роутерах с менее чем 1Гб RAM запускать контейнеры будет проблематично.
- Требуемая версия RouterOS v7.11+
Включить поддержку контейнеров в MikroTik
Проверьте, установлен ли на вашем роутере пакет container. Запустите WinBox, перейдите в раздел System -> Packages и проверьте есть ли он в списке.
Если пакет, отсутствует, скачайте официальный пакет с https://mikrotik.com/download (для вашей архитектуры и версии RouterOS).
Архитектуру и версию среды можно узнать так (в моем случае это arm64):
/system/resource/print


Загрузите скачанный NPK файл (container-7.24.5-arm64.npk) в корневой каталог роутера с помощью WinBox через Files -> Upload и перегрузите роутер.
Проверьте, что пакет container появился в списке доступных. Включите его.

Теперь нужно включить поддержку контейнеров на устройстве. Откройте консоль роутера и проверьте какие функции включены на роутере:
/system/device-mode/print

По умолчанию поддержка контейнеров отключена. Чтобы разрешить запуск контейнеров, выполните:
/system/device-mode/update container=yes
update: turn off power or reboot by pressing reset or mode button in 4m33s to -- [Q quit|D dump|C-z pause|right]

Для активации компонента нужно в течении 5 минут нужно перегрузить роутер физически (по питанию или кнопкой reset на корпусе).
После перезагрузки проверяем, включена ли поддержка контейнеров:
/system/device-mode/print

Настройка сети для контейнеров в MikroTik
Переходим к настройке сети для контейнеров. Начнем с создания бриджа для подключения контейнеров и виртуального сетевого интерфейса для первого контейнера.
Создаем бридж для контейнеров (можно использовать один для всех, или если нужно изолировать трафик контейнеров, можно создать несколько бриджей):
Interfaces -> Interface -> New Bridge. Имя
br_containers

Затем идем в IP -> Adresses и добавляем IP адрес
172.17.0.1/24
и подсеть для моста br_containers.

Создаем новый виртуальный интерфейс для подключения контейнера к сети (для каждого контейнера понадобится как минимум один сетевой интерфейс): Interfaces -> New -> VETH. Указываем имя
name
,
address
(IP адрес и маску подсети) и
gateway
(в качестве шлюза по умолчанию указывается IP адрес бриджа для контейнеров, который мы создадим далее).

Добавляем интерфейс verh1 в бридж br_containers (Bridge -> Ports).

Для быстрой настройки сети контейнеров можно использовать команды:
/interface/veth/add name=veth1 address=172.17.0.5/24 gateway=172.17.0.1
/interface/bridge/add name=br_containers
/ip/address/add address=172.17.0.1/24 interface=br_containers
/interface/bridge/port add bridge=containers interface=veth1
Создайте правило для выхода из подсети контейнеров в Интернет. В моем случае у меня уже есть глобальное srcnat (masquerade) для всех внутренних сетей:
/ip firewall nat
add action=masquerade chain=srcnat out-interface-list=WAN
Либо создайте кастомное правило masquerade для подсети контейнеров.

Подготовка USB хранилища для контейнеров Docker в MikroTik
Для хранения образов контейнеров Docker в MikroTik понадобится внешний USB SSD диск (сойдет и обычная USB флешка или SD карта, но ресурс и производительность такого хранилища, если используются дешевые бытовые накопители, будут ниже). И конечно, не стоит хранить контейнеры на встроенной флеш памяти роутера, это быстро убьет его ресурс.
Подключаем в USB порт диск и проверяем, что он виден:
/disk scan
/disk print

Форматируем диск в ext4 (все данные будут удалены)
/disk/format usb1 file-system=ext4

Создаем директории для контейнеров, временных файлов и тома для хранения данных:
/file add name=usb1/containers type=directory
/file add name=usb1/tmp type=directory
/file add name=usb1/layers type=directory
/file add name=usb1/volumes type=directory
Подключаем Docker Hub в качестве основного источника образов:
/container/config
set registry-url=https://registry-1.docker.io \
layer-dir=usb1/layers \
Вывести текущие настройки подсистемы контейнеров в разделе Containers -> Config или командой:
/container/config print
registry-url: https://registry-1.docker.io username: layer-dir: /usb1/layers tmpdir: memory-high: unlimited memory-max: unlimited memory-current: 0 swap-max: unlimited swap-current: 0

Запускаем первый контейнер на MikroTik
Переходим к настройке и запуску первого контейнера на роутере MikroTik. Мы будем разворачивать контейнер с Pi-hole, который будем использоваться в качестве простого локального DNS сервера для блокировки рекламы, телеметрии и управления черными/белыми списками сайтов для устройств в моей локальной сети.
Подготовим переменные окружения с базовыми настройками для нашего контейнера. Переменные можно создать через WinBox (Contaners -> Envs) или командами в консоли.
Мы задаем часовой пояс, имя администратора и пароль, вышестоящие upstream DNS сервера:
/container/envs/add list=ENV_PIHOLE key=TZ value="Europe/Moscow"
/container/envs/add list=ENV_PIHOLE key=DNSMASQ_USER value="root"
/container/envs/add list=ENV_PIHOLE key=FTLCONF_webserver_api_password value="MyPa33wo0rd"
/container/envs/add list=ENV_PIHOLE key=FTLCONF_dns_upstreams value="77.88.8.2; 77.88.8.88"
/container/envs/add list=ENV_PIHOLE key=FTLCONF_dns_listeningMode value="all"

Чтобы состояние контейнера не терялось при перезапуске, создадим точки монтирования (mounts), которые свяжут папки в контейнере с реальными папками на USB диске, в которых фактически будут хранится постоянные данные, которые должны сохраняться при перезапуске контейнера.
/container/mounts/add list=MOUNT_PIHOLE_PIHOLE src=usb1/volumes/pihole/pihole dst=/etc/pihole
/container/mounts/add list=MOUNT_PIHOLE_DNSMASQD src=usb1/volumes/pihole/dnsmasq.d dst=/etc/dnsmasq.d

Создаем tmpfs диск в RAM:
/disk add type=tmpfs tmpfs-max-size=100M slot=ram
Создаем точки монтирования для контейнера на RAM диске:
/container/mounts/add list=MOUNT_PIHOLE_TMP src=ram/tmp dst=/tmp
/container/mounts/add list=MOUNT_PIHOLE_LOG src=ram/log dst=/var/log/pihole
Также большую нагрузку на запись на USB флешку будет давать база данных SQLite
/etc/pihole/pihole-FTL.db
. Ее также можно перенести во временную память в RAM (при этом у вас не будет долговременной статистики запросов, которые будут сбрасываться при перезагрузке роутера).
Либо можно отключить логирование на диск в
/var/log/pihole/pihole.log
, сделать сброс логов в базу более редким (не каждую минуту, а раз в час) и ограничить срок хранения статистики 7 днями:
/container/envs/add list=ENV_PIHOLE key=FTLCONF_dns_queryLogging value="false"
/container/envs/add list=ENV_PIHOLE key=FTLCONF_database_maxDBdays value="7"
/container/envs/add list=ENV_PIHOLE key=FTLCONF_database_DBinterval value="3600"
Теперь мы готовы скачать образ контейнера Pi-hole:
/container/add name=pihole \
remote-image=pihole/pihole:latest \
interface=veth1 \
root-dir=usb1/containers/pihole \ mountlists=MOUNT_PIHOLE_PIHOLE,MOUNT_PIHOLE_DNSMASQD,MOUNT_PIHOLE_TMP,MOUNT_PIHOLE_LOG
envlist=ENV_PIHOLE \
logging=yes \
start-on-boot=yes
После чего начнется загрузка образа PiHole из Docker Hub (размер образа около 120 Мб).

После создания нового Docker‑контейнера в MikroTik автоматически загружается образ, выполняется его распаковка, и экземпляр переводится в состояние stopped. Для его активации необходимо однократно нажать кнопку Start. При успешном запуске рабочий статус контейнера изменится на running.

Либо проверяем, что образ загружен и запускаем его:
/container/print
/container/start pihole
Вывести лог загрузки контейнера (удобно для отладки):
/log/print where topics~"container"
Выводим состояние контейнера:
/container/print detail

По умолчанию веб-интерфейс контейнера Pi-hole доступен на порту 80. Для удобства, чтобы сделать веб интерфейс Pi-hole доступным напрямую по IP адресу вашего роутера MikroTik (вместо доступа по IP адресу в сети контейнеров), создадим такое NAT правило:
/ip/firewall/nat add action=dst-nat chain=dstnat \ dst-address=192.168.31.1 dst-port=80 protocol=tcp \ to-addresses=172.17.0.5 to-ports=80 comment="Pi-hole web"
Проверьте, что теперь веб интерфейс Pi-hole доступен на порту 80 вашего роутера:
http://192.168.31.1/admin/

Попробуйте выполнить вход с помощью пароля, заданного в переменнной
env
.

Осталось изменить настройки DHCP сервера на роутере MikroTik, чтобы клиенты в локальной сети обращались за разрешением имен к DNS серверу, запущенному в контейнере Pi-hole (172.17.0.5)
- Можно изменить только настройки DNS в DHCP сервере:
/ip dhcp-server network set [find] dns-server=172.17.0.5 - А можно настроить правила, чтобы ваш роутер пересылала все запросы на разрешение имен в контейнер Pi-hole:
/ip firewall nat add chain=dstnat action=dst-nat protocol=udp dst-port=53 to-addresses=172.17.0.5 comment="Force DNS to Pi-hole UDP"
/ip firewall nat add chain=dstnat action=dst-nat protocol=tcp dst-port=53 to-addresses=172.17.0.5 comment="Force DNS to Pi-hole TCP"
Смотрим, что на Pi-hole теперь отображается все DNS запросы из LAN.
Базовые команды для управления контейнерами MikroTik
Ограничить потребление оперативной памяти контейнером:
/container/config/set memory-high=200M
Включать автозапуск контейнера:
/container/set pihole start-on-boot=yes
Вывести список контейнеров:
/container print
Подробный вывод:
/container print detail
Запустить контейнер по его номеру:
/container start 0
Запустить по имени:
/container start [find where name~"pihole"]
Остановить контейнер по номеру:
/container stop 0
Подключиться в оболочку (shell) контейнера, что бывает удобно для выполнения диагностики и доступности изнутри контейнера:
/container/shell 0

Вывести логи определённо контейнера:
/container/log print where container=pihole
Контейнеры в MikroTik можно использовать для расширения возможностей роутера, и реализации функционала, который отсутствует или не полностью представлен в RouteOS. Например, сторонние VPN сервера/клиенты, DNS фильтрация, мониторинг и сбор логов, обратное проксирование, торрент клиенты, и многое другое.

