Для работы с MikoPBX в контейнере необходимо установить docker и docker compose, а также создать пользователя и папки для хранения настроек конфигурации и записей разговоров по инструкции
Вот пример файла docker-compose.yml, который может быть использован для управления вашим контейнером MikoPBX через Docker Compose:
docker-compose.yml
services:mikopbx:container_name:"mikopbx"image:"ghcr.io/mikopbx/mikopbx-x86-64"network_mode:"host"cap_add: - NET_ADMINentrypoint:"/sbin/docker-entrypoint"hostname:"mikopbx-in-a-docker"volumes: - /var/spool/mikopbx/cf:/cf - /var/spool/mikopbx/storage:/storagetty:trueenvironment: - ID_WWW_USER=${ID_WWW_USER} - ID_WWW_GROUP=${ID_WWW_GROUP}# Изменение имени станции через переменные окружения - PBX_NAME=MikoPBX-in-Docker# Изменение стандартного порта SSH на 23 - SSH_PORT=23# Изменение стандартного порта WEB на 8080 - WEB_PORT=8080# Изменение стандартного порта WEB HTTPS на 8443 - WEB_HTTPS_PORT=8443
Сохраните содержимое в файл docker-compose.yml, выполните необходимые корректировки и запускайте MikoPBX коммандой:
Режим без изоляции сети хоста от контейнеров (–net=host)
Также можно оганизовать запуск нескольких контенеров MikoPBX на одном хосте, но здесь надо учитывать особенности работы Docker с портами, если не использовать режим –net=host то это приведет к высокой нагрузке на процессор хостовой системы, т.к. Docker создает для каждого выделенного порта отдельное правило в Iptables.
С включенным режимом –net=host вам необходимо вручную следить за распределением доступных портов между запускаемыми контейнерами и встроенными приложениями.
Например, для запуска двух контейнеров с MikoPBX на одном хосте, можно использовать следующий конфигурационный файл:
Существует вариант запуска контейнеров с MikoPBX в режиме –net=bridge, но как описано выше для использования этого режима необходимо или существенно ограничить диапазон RTP портов, или открывать к ним доступ на хостовой машине не используя возможности Docker.
Для этого вам необходимо написать небольшой скрипт, для определения имени текущего мостового интерфейса и IP адреса каждого контейнера, и после запуска docker compose добавить необходимые правила iptables для диапазона RTP портов следующим образом:
start-multiple-mikopbx.sh
#!/bin/bashCOMPOSE_FILE="$1"if [ -z"$COMPOSE_FILE" ]; thenecho"Usage: $0 path/to/docker-compose.yaml"exit1fi# Получим идентификатор пользователя для запуска контейнераexport ID_WWW_USER=$(id-uwww-user)export ID_WWW_GROUP=$(id-gwww-user)# Оставновим текущие контейнеры, если они запущеныdockercompose-f"$COMPOSE_FILE"down# Удалим ихdockercompose-f"$COMPOSE_FILE"rm# Запускаем контейнеры в фонеdockercompose-f"$COMPOSE_FILE"up-dsleep60# Создадим метку для правил IPTABLESIPTABLES_COMMENT="mikopbx-custom-rule"# Определим идентификатор проекта, он используется при создании сетевого мостаproject_prefix=$(cat"$COMPOSE_FILE"|yqe'.x-project-name'-)# Если префикс не задан, устанавливаем значение по умолчаниюif [ -z"$project_prefix" ]; then project_prefix="default_prefix"fi# Функция для получения IP адреса контейнераfunctionget_container_ip() {dockerinspect-f'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'"$1"}# Функция для получения имени мостового интерфейсаfunctionget_bridge_name() {local network_name="$1"local prefix="$2"local network_id=$(dockernetworkinspect"${prefix}_${network_name}"-f'{{.Id}}')if [ -z"$network_id" ]; thenecho"Error: Network ${prefix}_${network_name} not found."return1filocal bridge_name=$(iplinkshowtypebridge|grep-o"br-${network_id:0:12}\b")echo $bridge_name}echo"Delete tagged iptables rules"# Удаляем все правила iptables промаркированные нашим комментариемiptables-S|grep"$IPTABLES_COMMENT"|sed's/-A /-D /'|whilereadrule; doecho"Delete rule $rule"iptables $ruledone# Удаляем все NAT правила iptables промаркированные нашим комментариемiptables-S-tnat|grep"$IPTABLES_COMMENT"|sed's/-A /-D /'|whilereadrule; doecho"Delete rule $rule"iptables-tnat $ruledone# Парсим docker-compose файл и получаем все необходимые параметры.echo"Parsing docker-compose file and configuring iptables rules"cat "$COMPOSE_FILE" | yq e '.services[] | select(.environment[] | test("RTP_PORT_FROM")) | {"container_name": .container_name, "environment": .environment, "network": .networks[0]}' -o=json | jq -c '.' | while read -r service; do
container_name=$(echo $service |jq-r'.container_name') network_name=$(echo $service |jq-r'.network') bridge_name=$(get_bridge_name"$network_name""$project_prefix") container_ip=$(get_container_ip"$container_name") RTP_PORT_FROM=$(echo $service |jq-r'.environment[] | select(contains("RTP_PORT_FROM")) | split("=")[1]') RTP_PORT_TO=$(echo $service |jq-r'.environment[] | select(contains("RTP_PORT_TO")) | split("=")[1]') echo "Configuring iptables for $container_name ($container_ip) on $bridge_name from port $RTP_PORT_FROM to $RTP_PORT_TO"
iptables -A DOCKER -t nat ! -i "$bridge_name" -p udp -m udp --dport $RTP_PORT_FROM:$RTP_PORT_TO -j DNAT --to-destination $container_ip:$RTP_PORT_FROM-$RTP_PORT_TO -m comment --comment "$IPTABLES_COMMENT"
iptables -A DOCKER -d $container_ip/32 ! -i "$bridge_name" -o "$bridge_name" -p udp -m udp --dport $RTP_PORT_FROM:$RTP_PORT_TO -j ACCEPT -m comment --comment "$IPTABLES_COMMENT"
iptables -A POSTROUTING -t nat -s $container_ip/32 -d $container_ip/32 -p udp -m udp --dport $RTP_PORT_FROM:$RTP_PORT_TO -j MASQUERADE -m comment --comment "$IPTABLES_COMMENT"
echo"Don't forget to open UDP ports $RTP_PORT_FROM to $RTP_PORT_TO on external firewall if it exists"doneecho"iptables configuration completed successfully."
Опишем несколько контейнеров в файле docker-compose.yaml, определим разные порты для веб интерфейса, SIP портов и диапазоны RTP портов, чтобы они не пересекались.
docker-compose.yaml
services:mikopbx-first:container_name:"mikopbx-first"image:"ghcr.io/mikopbx/mikopbx-x86-64"entrypoint:"/sbin/docker-entrypoint"hostname:"mikopbx-in-docker-first"volumes: - /var/spool/mikopbx/first/cf:/cf - /var/spool/mikopbx/first/storage:/storagetty:truecap_add: - net_adminnetworks: - network-bridge1environment: - ID_WWW_USER=${ID_WWW_USER} - ID_WWW_GROUP=${ID_WWW_GROUP} - PBX_NAME=MikoPBXFirst - RTP_PORT_FROM=10000# UPD дипазон 10000-10800 на хосте будет направлен в контейнер - RTP_PORT_TO=10800 - WEB_ADMIN_PASSWORD=mikopbx-first-password - ENABLE_USE_NAT=1 - PBX_FIREWALL_ENABLED=1 - PBX_FAIL2BAN_ENABLED=1ports: - "8443:443"# TCP порт 9443 на хосте направляется на порт 443 в контейнере - "5060:5060/udp"# UDP порт 5060 на хосте направляется на порт 5060 в контейнереmikopbx-second:container_name:"mikopbx-second"image:"ghcr.io/mikopbx/mikopbx-x86-64"tty:truecap_add: - net_adminnetworks: - network-bridge2entrypoint:"/sbin/docker-entrypoint"hostname:"mikopbx-in-docker-second"volumes: - /var/spool/mikopbx/second/cf:/cf - /var/spool/mikopbx/second/storage:/storageenvironment: - ID_WWW_USER=${ID_WWW_USER} - ID_WWW_GROUP=${ID_WWW_GROUP} - PBX_NAME=MikoPBXSecond - RTP_PORT_FROM=20000# UPD дипазон 20000-20800 на хосте будет направлен в контейнер - RTP_PORT_TO=20800 - EXTERNAL_SIP_PORT=6060# Расскажем MikoPBX какой у нее внешнить SIP порт - WEB_ADMIN_PASSWORD=mikopbx-second-password - ENABLE_USE_NAT=1 - PBX_FIREWALL_ENABLED=1 - PBX_FAIL2BAN_ENABLED=1ports: - "9443:443"# TCP порт 9443 на хосте направляется на порт 443 в контейнере - "6060:5060/udp"# UDP порт 6060 на хосте направляется на порт 5060 в контейнереx-project-name:mikopbx# Этот параметр обязательно должен присуствоватьnetworks:network-bridge1:driver:bridgenetwork-bridge2:driver:bridge
Создаем папку для скриптов
mkdir-p/usr/src/mikopbx
Сохраняем файлы start-multiple-mikopbx.sh и docker-compose.yaml в эту папку.
Устанавливаем необходимые зависимости для работы скрипта.
Пока ожидаем запуск контейнеров, проверяем настройки брендмауера на хосте, при необходимости открваем те порты, которые указаны в нашем docker-compose.yaml файле, а именно:
TCP/UDP порты 5060 и 6060 для SIP
UDP диапазоны 10000-10800 и 20000-20800 для передачи звука по RTP
TCP порты 8443 и 9443 для HTTPS протокола, для работы Web интерфейса.
Входим по очереди на каждую из станций по адресам:
https://<IP хостовой машины>:8443
https://<IP хостовой машины>:9443
Для входа в веб-интерфейс первой АТС MikoPBX используйте логин admin и пароль mikopbx-first-password
Для входа в веб-интерфейс второй АТС MikoPBX используйте логин admin и пароль mikopbx-second-password
В каждой машине должен быть включен режим NAT, указывая что контейнер находится за маршрутизатором в настройках сетевого интерфейса. Если станции будут использоваться внутри локальной сети, то в поле внешнего IP прописваем локальный IP адрес хостовой машины, в противном случе ее публичный IP адрес.
Важное замечание!
Один из наших контейнеров использует проброс с SIP порта с изменением его значения 5060 -> 6060.
В данном случае, для корректной работы системы, необходимо добавить внешнее значение SIP порта в настройках NAT в разделе сетевых интерфейсов MikoPBX.
Эту настройку также можно сделать задав соответвующее значение переменной окружения EXTERNAL_SIP_PORT=6060 в файле docker-compose.
На этом настройка завершена, можно настраивать учетные записи и выполнять звонки.
Переменные окружения для конфигурирования MikoPBX
Ниже перечислены некоторые переменные окружения, которые позволят скорректировать используемые MikoPBX порты и настройки.
SSH_PORT - порт для SSH (22)
WEB_PORT - порт для работы web интерфейса по протоколу HTTP (80)
WEB_HTTPS_PORT - порт для работы web интерфейса по протоколу HTTPS (443)
SIP_PORT - порт для подключения SIP клиента (5060)
TLS_PORT - порт для подключения SIP клиента с шифрованием (5061)
RTP_PORT_FROM - начало диапазона RTP портов, передача голоса (10000)
RTP_PORT_TO - конец диапазона RTP портов, передача голоса (10800)
IAX_PORT - порт для подключения IAX клиентов (4569)
AMI_PORT - порт AMI (5038)
AJAM_PORT - порт AJAM используется для подключения панели телефонии для 1С (8088)
AJAM_PORT_TLS - порт AJAM используется для подключения панели телефонии для 1С (8089)
BEANSTALK_PORT - порт для сервера очередей Beanstalkd (4229)
REDIS_PORT - порт для сервера Redis (6379)
GNATS_PORT - порт для сервера gnatsd (4223)
ID_WWW_USER - идентификатор пользователя www-user (можно задать выражением $(id -u www-user), где www-user имя НЕ root пользователя)
ID_WWW_GROUP - идентификатор группы www-user (можно задать выражением $(id -g www-user), где www-user имя НЕ root группы)
WEB_ADMIN_LOGIN - логин для доступа в Web интерфейс
WEB_ADMIN_PASSWORD - пароль для доступа в Web интерфейс
Полный список всех возможных параметров настроек доступен в исходном коде по ссылке.