Добрый день дорогой читатель, данное повествование не является
истиной в последней инстанции, это некая инструкция по установке, настройке и
работе (в основном для собственного пользования) с docker контейнером MiniDLNA на Arch Linux с пояснениями и все возможными мыслями. Так же подобные действия применимы и к другим дистрибутивам.
Немного описания с чем придется по работать.
MiniDLNA, также известный как ReadyMedia, это легковесный DLNA/UPnP медиа-сервер. Он позволяет предоставлять общий доступ к медиафайлам (видео, аудио, изображения) по локальной сети, используя протокол DLNA/UPnP. Другими словами, MiniDLNA превращает компьютер или NAS-устройство в сервер, к которому могут подключаться другие устройства в сети (телевизоры,
игровые приставки, смартфоны), чтобы просматривать и воспроизводить
медиаконтент.
Docker – это платформа для автоматизации развертывания, доставки и запуска приложений с использованием технологии контейнеризации. Простыми словами, Docker позволяет упаковать приложение и его зависимости в контейнер, который затем можно легко переносить и запускать на любой
машине с установленным Docker.
Docker Compose – это инструмент, который упрощает управление многоконтейнерными приложениями Docker. Он позволяет определять и запускать сразу несколько связанных контейнеров, описанных в едином конфигурационном файле, обычно в формате YAML.
О Docker и Docker Compose достаточно много инструкций и уроков, по этому заострять на них внимание не будем. Но все же максимально поясню все действия.
Межсетевой экран. Забегая вперед хочу немного отклониться от основной темы и затронуть тему межсетевого экрана, вероятно вы как и я используете firewalld это можно проверить командой
sudo systemctl status firewalld
Нюанс. так как у меня запущен firewalld посмотрев выхлоп выше на писаной команды после запуска docker видим он не понимает созданные docker правила, которые предназначены для iptables и по этому вылетели предупреждения. Вариант решения этой проблемы два:
- переписать правила docker под firewalld (тут у меня сомнения)
- вместо firewalld использовать iptables, но в дальнейшем довести до ума.
будем использовать второй вариант, останавливаем firewalld и запускаем iptables
sudo systemctl disable firewalld
sudo systemctl stop firewalld
sudo systemctl status firewalld
Запускаем iptables до боле знакомыми командами. В контексте iptables я буду иметь в виду iptables и ip6tables, так как я пользуюсь IPv4 и IPv6
sudo systemctl enable iptables
sudo systemctl enable ip6tables
sudo systemctl restart iptables
sudo systemctl restart ip6tables
sudo systemctl status iptables
sudo systemctl status ip6tables
Так как только запустили давайте сбросим все настройки для IPv4 и IPv6 следующими командами:
sudo iptables -F
sudo iptables -X
sudo iptables -Z
sudo ip6tables -F
sudo ip6tables -X
sudo ip6tables -Z
по ключам
- -F --flush - Очищает (удаляет) все правила в указанной цепочке или во всех цепочках, если цепочка не указана. Правила удаляются, но цепочки остаются.
- -X --delete-chain - Удаляет все пользовательские цепочки
- -Z --zero - Обнуляет счётчики пакетов и байт во всех во всех цепочках, если цепочка не указана. Правила остаются, но счётчики обнуляются.
далее установим политику по умолчанию блокировать входящие(INPUT), разрешать исходящие(OUTPUT), блокировать форвардинг(FORWARD) (хотя бы базовая защита для клиента именно клиента а не сервера) для IPv4 и IPv6, на данном этапе интернет исчезнет, не пугайтесь мы это поправим
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
sudo ip6tables -P INPUT DROP
sudo ip6tables -P FORWARD DROP
sudo ip6tables -P OUTPUT ACCEPT
по ключам
- -P --policy - устанавливает политику по умолчанию для цепочки
что бы проверить выполним команду
sudo iptables -nvL
давайте разберем параметры
-n --numeric - Выводить IP-адреса и порты в числовом виде, не пытаясь разрешать их в имена хостов или сервисов. Это ускоряет вывод и делает его более однозначным.
-v --verbose - Включить подробный (подробный) вывод, показывая дополнительную информацию, такую как количество пакетов и байт, счетчики, интерфейсы и т.д.
-L --list - Вывести список правил в таблице фильтрации (filter table) по умолчанию.
аналогичто для IPv6
sudo ip6tables -nvL
ну и конечно же сохраним правила
su
iptables-save > /etc/iptables/iptables.rules
ip6tables-save > /etc/iptables/ip6tables.rules
exit
Теперь добавим правила разрешающие входящие пакеты, относящиеся к уже установленным соединениям
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
и разрешить loopback-интерфейс (localhost)
iptables -A INPUT -i lo -j ACCEPT
аналогично и для IPv6
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
по параметрам
- -A --append - добавляет правило в указанную цепочку в данном случае INPUT - входящие
- -i - интерфейс какй подвергается фильтрованию в данном случае lo локальный(localhost)
- -m conntrack Это означает использование модуля conntrack который позволяет фильтровать пакеты по состоянию их соединения.
- --ctstate - Определяет, какие состояния соединения интересуют правило. Можно перечислить несколько состояний через запятую. В данном случае нас интересовали два состояния соединения
ESTABLISHED — пакет принадлежит уже существующему, установленному соединению. Например, ответ на запрос, который уже прошёл.
RELATED — пакет связан с уже установленным соединением, но не является его частью напрямую. Например, ICMP ошибки или FTP соединения данных, которые связаны с управляющим соединением.
- -j - что делать с пакетами в данном случае ACCEPT - разрешить
и сохраним
su
iptables-save > /etc/iptables/iptables.rules
ip6tables-save > /etc/iptables/ip6tables.rules
exit
на всякий случай проверяем есть ли интернет например
ping ya.ru
немного обезопасив себя вернемся к основной теме
В принципе действия описанные ниже можно отнести к опциональным. В основном делаю для более короткого пути к медиафайлам. Можно было бы перемонтировать раздел (вероятно даже лучше чтоб автоматически монтировался при загрузке например через fstab), но я решил воспользоваться simlink'ами. Приступим
mkdir -p ~/minidlna/media
ls -l ~/minidlna
ln -s /run/media/john/d4cc62ed-dfdd-46e6-8af9-be4f22f6d53a/Nas/video ~/minidlna/media
ls -l ~/minidlna/media/video/
Установка. Для этого нам потребуется установить docker и docker-compose (опционально) так как будем использовать MiniDLNA в контейнере
sudo pacman -S docker docker-compose
добавим текущего пользователя в группу docker
groups $USER
sudo usermod -aG docker $USER
groups $USER
sudo systemctl daemon-reload
далее запустим docker и добавим в автозапуск
sudo systemctl enable docker
sudo systemctl restart docker
sudo systemctl status docker
Теперь посмотрим следующими командами какие правила добавил docker
sudo iptables -nvL
аналогично по IPv6
sudo ip6tables -nvL
переходим к запуску контейнера minidlna
docker run -d --rm --name minidlna -p 1900:1900/udp -p 8200:8200 --net=host -v /home/john/minidlna/media/video/:/media -e MINIDLNA_MEDIA_DIR=/media -e MINIDLNA_FRIENDLY_NAME=MyMiniDLNA vladgh/minidlna
давайте по подробнее разберем параметры
- docker run - Запустить новый контейнер.
- -d - Запуск контейнера в фоновом режиме (detached mode).
- --rm - удаление контейнера после остановки
- --name minidlna Задать имя контейнера — minidlna. Это удобно для управления (остановка, запуск, удаление по имени).
- -p 1900:1900/udp - Проброс порта 1900 UDP с хоста в контейнер. Порт 1900 UDP используется протоколом SSDP (Simple Service Discovery Protocol), необходим для обнаружения DLNA-серверов в сети.
- -p 8200:8200 - Проброс порта 8200 TCP с хоста в контейнер. Обычно порт 8200 используется для веб-интерфейса MiniDLNA или DLNA-сервера.
- --net=host - Использовать сетевой стек хоста напрямую (без сетевого мостового интерфейса Docker). Это значит, что контейнер будет использовать IP-адреса и порты хоста напрямую.
- -v /home/john/minidlna/media/video/:/media - Примонтировать локальную директорию /home/john/minidlna/media/video/ в контейнер по пути /media. Это позволяет контейнеру получить доступ к медиафайлам на хосте.
- -e MINIDLNA_MEDIA_DIR=/media - Установить переменную окружения MINIDLNA_MEDIA_DIR внутри контейнера передав значение /media. MiniDLNA будет сканировать эту директорию для медиафайлов.
- -e MINIDLNA_FRIENDLY_NAME=MyMiniDLNA - Установить переменную окружения MINIDLNA_FRIENDLY_NAME передав значение MyMiniDLNA. Это имя, под которым DLNA-сервер будет виден в сети.
- vladgh/minidlna - Имя Docker-образа, из которого запускается контейнер. В данном случае контейнер берется с DockerHub
Нюанс. Если обратили внимание на предупреждение(warning) в котором по сути говориться если контейнер запущен в сети хоста то не обязательно указывать порты. Проверив на практики, да это работает.
проверяем в браузере корректно ли запустился, в данном случае докер запущен на машине с IP 192.168.0.4, следовательно переходим по IP 192.168.0.4:8200 так как в сети хоста
обратиться можно только с IP 192.168.0.4 так как у нас не настроен проброс портов в локальную сеть(в данный момент запущен iptables он не пустит из локальной сети трафик в контейнер). Надо написать правила для iptables.
И так наш контейнер miniDLNA запущен в сети host(так как ip как у хоста) следовательно он использует весь сетевой стек хоста, исходя из этого нам остается открыть на хосте порты 8300 и 1900, приступим
открыть порт 8200 для TCP-трафика и 1900 для UDP-трафика из локальной сети 192.168.0.0/24, выполнив следующие команды:
sudo iptables -A INPUT -p tcp --dport 8200 -s 192.168.0.0/24 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 1900 -s 192.168.0.0/24 -j ACCEPT
давайте разберем команды
- -A INPUT — добавляем правило в цепочку INPUT (входящие пакеты).
- -p tcp — протокол TCP.
- -p udp — протокол UDP.
- --dport 8200 — порт назначения 8200.
- --dport 1900 — порт назначения 1900.
- -s 192.168.0.0/24 — источник пакета из локальной подсети .
- -j ACCEPT — разрешить этот трафик.
и сохраним их выполнив команду под root
su
iptables-save > /etc/iptables/iptables.rules
ip6tables-save > /etc/iptables/ip6tables.rules
exit
после добавления вышесказанных правил хост пропускает трафик из локальной сети в контейнер и соответственно медиатека доступна для других устройств в локальной сети. Видим на нижнем скрине после добавления правил соответствующую картину
P.S. В данном случае нет автоматизации запуска (пока не решил вероятно дополню), если надо автоматизировать то директория с медиа должна быть доступна для контейнера, а контейнер должен запускаться автоматически в данном случае решение написать unit для systemd либо же вся автоматизация ляжет на плечи bash-скрипта. Пока в размышлениях.
В дальнейшем я пересмотрел нюанс с медиатекой сделал аналогично но чуть по другому
создал директорию куда монтируется хранилище
sudo mkdir /mnt/storage
монтирую хранилище так как я использую lvm то соответственно оно находится по пути /dev/mapper/
sudo mount /dev/mapper/storage-lv_date /mnt/storage
создал симлинки на медиатеку
sudo ln -s /mnt/storage/Nas/video ~/minidlna/media
убедился что все отображается корректно
ls ~/minidlna/media/video
далее написал два скрипта один запускает другой останавливает minidlna
sudo nano /usr/local/bin/minidlna-start.sh
содержимое скрипта
#!/bin/bash
sudo mount /dev/mapper/storage-lv_date /mnt/storage
docker run -d --rm --name minidlna -p 1900:1900/udp -p 8200:8200 --net=host -v /home/john/minidlna/media/video/:/media -e MINIDLNA_MEDIA_DIR=/media -e MINIDLNA_FRIENDLY_NAME=MyMiniDLNA vladgh/minidlna
sudo nano /usr/local/bin/minidlna-stop.sh
содержимое скрипта, но тут нюанс, данный скрипт останавливает все контейнеры, и не следует использовать если запущены другие контейнеры, следует останавливать контейнер по имени. То есть командой docker stop minidlna
#!/bin/bash
docker stop $(docker ps -a -q)
sudo umount /mnt/storage
и конечно же выставить права на запуск скриптов
sudo chmod +x /usr/local/bin/minidlna-stop.sh
sudo chmod +x /usr/local/bin/minidlna-start.sh
далее к ним можно обращаться по имени то есть
minidlna-start.sh # запустили minidlna
minidlna-stop.sh # остановили minidlna
Как реализовать запуск через SystemD в следующей статье MiniDLNA часть 2 (Запуск через Unit'ы SystemD)
За основу взята документация по Docker, а так же информация с форумов по данной тематике, информация других пользователей размещенная на просторах всемирной паутины и собственные наработки.
За сим откланиваюсь...