Общее описание
С версии SoftWLC 1.25 возможен запуск сервиса eltex-wifi-cab в docker-контейнере.
Описанный алгоритм содержит особенности запуска контейнера в режиме однохостовой и многохостовой установки SoftWLC.
Подготовка окружения
Разрешение доступа к БД MongoDB
Чтобы разрешить доступ до БД с любого адреса необходимо:
- указать
bindIp: 0.0.0.0
в /etc/mongod.conf
- перезапустить сервис
mongod
sudo cp /etc/mongod.conf /etc/mongod.conf.bak
sudo sed -i -e "s/\(.*bindIp:\)\(.*\)/#\1\2\n\1 0.0.0.0/g" /etc/mongod.conf
sudo systemctl restart mongod.service
Загрузка Eltex OUI list
Если на машине, на которой предполагается запуск контейнера, не установлен пакет eltex-oui-list, то необходимо установить его. В дальнейшем текстовая база данных /usr/share/oui-base/oui-small.txt будет смонтирована в контейнер как внешний том данных.
sudo apt update
sudo apt install eltex-oui-list
Подготовка файлов конфигурации
Для запуска сервиса требуется создать папку для запуска контейнера и в ней подготовить файлы конфигурации, представленные далее.
Файл local_secret
Если контейнер запускается на машине, на которой ранее был установлен сервис Личного кабинета, то существующий файл можно смонтировать в контейнер в директорию /etc/eltex-wifi-cab/local_secret. Если необходимо сгенерировать файл с секретом, то можно воспользоваться командой
echo $(head -c 16 /dev/random | hexdump -e '"%02x"') > local_secret
В противном случае при старте контейнера секрет будет генерироваться заново, и при выполнении POST запросов к Личному кабинету из EMS будет возникать ошибка из-за неверно указанного в настройках EMS секрета.
Файл system.xml
Файл с настройками system.xml по умолчанию будет смонтирован в /etc/eltex-wifi-cab/system.xml. Если Вы ранее использовали Личный кабинет и уже имеете файл с настройками, то поместите его в ранее созданную папку. Если Вы не имеете существующего файла настроек, то скопируйте и отредактируйте согласно конфигурации Вашей системы следующий файл:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="mongoaddress">mongodb://ip_адрес_mongo:27017/wifi-customer-cab</entry>
<entry key="nbiaddress">http://ip_адрес_nbi:8080/axis2/services/RadiusNbiService?wsdl</entry>
<entry key="nbi.serviceLogin.user">softwlc_service</entry>
<entry key="nbi.serviceLogin.password">softwlc</entry>
<entry key="nbi.serviceLogin.requestTimeout.sec">120</entry>
<!--Bonnie or NBI-->
<entry key="data.service.type">NBI</entry>
<entry key="bonnie.service.host">ip_адрес_bonnie</entry>
<entry key="bonnie.service.port">9070</entry>
<!--Bruce-->
<entry key="bruce.service.host">ip_адрес_bruce</entry>
<entry key="bruce.service.port">8008</entry>
<!-- Support link -->
<entry key="support.page.enabled">false</entry>
<entry key="support.page.url">http://eltex-co.ru</entry>
<!-- DPI link -->
<entry key="dpi.page.enabled">false</entry>
<entry key="dpi.page.url">https://filter.wifi.example.org/</entry>
<!-- SSO Settings -->
<entry key="sso.enabled">false</entry>
<entry key="sso.redirectUri">http://ip_адрес_sso:8080/wifi-cab/sso</entry>
<entry key="sso.clientSecret"></entry>
<entry key="sso.clientId"></entry>
<!-- SSO Auth -->
<entry key="sso.auth.server.protocol">http</entry>
<entry key="sso.auth.server.address"></entry>
<entry key="sso.auth.server.port">80</entry>
<entry key="sso.auth.auth.path">/auth/realms/b2b/protocol/openid-connect/auth</entry>
<entry key="sso.auth.logout.path">/auth/realms/b2b/protocol/openid-connect/logout</entry>
<!-- SSO REST -->
<entry key="sso.rest.server.protocol">http</entry>
<entry key="sso.rest.server.address"></entry>
<entry key="sso.rest.server.port">80</entry>
<entry key="sso.rest.server.timeout.sec">10</entry>
<entry key="sso.rest.protocol.version">2.0</entry>
<entry key="sso.rest.username"></entry>
<entry key="sso.rest.password"></entry>
<entry key="sso.rest.getToken.path">/apiman-gateway/b2b_test/getToken</entry>
<entry key="sso.rest.getUserInfo.path">/apiman-gateway/b2b_test/getUserInfo</entry>
<entry key="sso.rest.addUser.path">/apiman-gateway/b2b_test/addUser</entry>
<entry key="sso.rest.updateUser.path">/apiman-gateway/b2b_test/updateUser</entry>
<entry key="sso.rest.delUser.path">/apiman-gateway/b2b_test/delUser</entry>
<entry key="sso.rest.addUserParam.path">/apiman-gateway/b2b_test/addUserParam</entry>
<entry key="sso.rest.delUserParam.path">/apiman-gateway/b2b_test/delUserParam</entry>
<entry key="sso.rest.getUserByName.path">/apiman-gateway/b2b_test/getUserByName</entry>
<entry key="sso.rest.resetPassword.path">/apiman-gateway/b2b_test/resetPassword</entry>
<entry key="sso.rest.getUserByParam.path">/apiman-gateway/b2b_test/getUserByParam</entry>
<entry key="sso.rest.getUserByEmail.path">/apiman-gateway/b2b_test/getUserByEmail</entry>
</properties>
Настройки данного файла предполагают однохостовую установку с параметрами по умолчанию. Если Вы изменили параметры по умолчанию или сервисы SoftWLC установлены в многохостовом режиме, то измените соответствующие параметры. Значения параметров, используемых в файле, можно посмотреть в документации Личного кабинета в разделе v1.26_Администрирование Личного кабинета.
Файл лицензии
Файл лицензии licence.xml по умолчанию будет смонтирован в /etc/eltex-wifi-cab/licence.xml. Имеющийся у Вас файл лицензии разместите в ранее созданой папке с файлами конфигурации. Если у Вас нет файла лицензии, то использование Личного кабинета возможно в демо-режиме с ограничениями на количество пользователей. Подробнее о лицензировании Личного кабинета Вы можете узнать в документации v1.26_Администрирование Личного кабинета.
Файлы docker
Для запуска сервиса требуется подготовить файл с переменными окружения ".env" и файл конфигурации для запуска сервиса с помощью docker-compose "docker-compose.yml". Ниже преведены примеры данных файлов с настройками по умолчанию.
version: '3'
services:
eltex-wifi-cab:
container_name: eltex-wifi-cab
image: ${ELTEX_HUB}/eltex-wifi-cab:${SWLC_VERSION}
restart: unless-stopped
ports:
- "8083:8083/tcp"
hostname: wifi-cab-docker
env_file: .env
environment:
# Настройки таймзоны
- TZ=${TZ}
# Настройки логирования
- LOG_LEVEL=DEBUG
- CONSOLE_LEVEL=INFO
- LOGGER_DEFAULT_LEVEL=OFF
- LOGGER_SCHEDULER_LEVEL=OFF
- LOGGER_EXPORT_LEVEL=OFF
- LOGGER_I18N_LEVEL=OFF
- LOGGER_LICENCE_LEVEL=OFF
- LOGGER_QUARTZ_LEVEL=OFF
- LOGGER_MONGODB_DRIVER_LEVEL=INFO
- LOGGER_NBI_LEVEL=OFF
- LOGGER_SPRING_LEVEL=OFF
# Настройки Graylog
- GELF_LEVEL=${GELF_LEVEL}
- GELF_HOST=${GELF_HOST}
- GELF_PORT=${GELF_PORT}
volumes:
- "./system.xml:/etc/eltex-wifi-cab/system.xml:ro"
- "./local_secret:/etc/eltex-wifi-cab/local_secret:ro"
# Файл лицензии. Закомментируйте строку ниже, если у Вас его нет
- "./licence.xml:/etc/eltex-wifi-cab/licence.xml:ro"
# Eltex OUI list
- /usr/share/oui-base/oui-small.txt:/usr/share/oui-base/oui-small.txt:ro
# HeapDumpPath
# execute before: sudo chown -R 100001:100001 ./eltex-wifi-cab/java-heap-dump
- ./eltex-wifi-cab/java-heap-dump:/var/log/java-heap-dump
# Logs
# - ./log4j2-docker.xml:/etc/eltex-wifi-cab/log4j2-docker.xml
# execute before: sudo mkdir -p /var/log/eltex-wifi-cab && chown -R 100001:100001 /var/log/eltex-wifi-cab
# - /var/log/eltex-wifi-cab:/var/log/eltex-wifi-cab
# Публичный docker registry: hub.eltex-co.ru/softwlc
ELTEX_HUB=hub.eltex-co.ru/softwlc
# Версия сервиса, которую нужно развернуть
SWLC_VERSION=1.25-latest
# Настройки таймзоны
TZ=Asia/Novosibirsk
# Настройки Graylog
# Вместо <graylog_server_ip> (по умолчанию localhost) нужно указать адрес сервера Graylog
GELF_LEVEL=OFF
GELF_HOST=udp:localhost
GELF_PORT=12201
Запуск контейнера
Для запуска контейнера перейдите в папку, в которой расположены файлы конфигурации, и выполните команду
sudo docker-compose up -d
Контейнер будет запущен в фоновом режиме.
Проверка доступности сервиса
После запуска контейнера доступность Личного кабинета можно проверить с помощью curl :
curl http://localhost:8083/wifi-cab/
или перейдя в браузере по указанной URL с адресом хоста, на котором запущен контейнер.
Для сервиса поддержана автоматическая проверка состояния работы сервиса с помощью средств docker. Текущее состояние контейнера можно посмотреть с помощью команды docker ps:
docker ps -f name=eltex-wifi-cab
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8ada5bef10d5 hub.eltex-co.ru/softwlc/eltex-wifi-cab:1.25-latest "/entrypoint.sh" 4 hours ago Up 3 hours (healthy) 0.0.0.0:8083->8083/tcp, :::8083->8083/tcp eltex-wifi-cab
Нормальному состоянию работы сервиса соответствует статус healthy. Команда, запускаемая docker для проверки состтояния работы сервиса
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=1m \
CMD curl -f http://localhost:8083/wifi-cab/service/livez || exit 1
Особенности запуска контейнера на хосте, где уже запущен сервис ЛК
Если Вы запускаете docker-контейнер на хосте, где уже запущен сервис Личного кабинета, то необходимо остановить сервис и/или удалить пакет eltex-wifi-cab с сохранением базы данных:
sudo systemctl stop eltex-wifi-cab.service
sudo apt purge eltex-wifi-cab
...
Remove mongo 'wifi-customer-cab' database? [y/N] N
..
Настройки после запуска контейнера
После запуска контейнера и входа в Личный кабинет необходимо настроить URL PCRF, NGW и Конструктора порталов во вкладке Настройка - Система - Интеграция. Более подробно данные настройки описаны в v1.25_Администрирование Личного кабинета.
Управление логированием
В рамках поддержанных переменных окружения можно указать уровень логирования сервиса eltex-wifi-cab и вывод логов в консоль или отправку на сторонний сервер. Значения переменных задаются в файлах "docker-compose.yml" и ".env".
Реализована следующая поддержка логирования:
- Логи root level и от логгеров default, org.quartz, org.mongodb.driver выводятся в STDOUT и/или на сервер Graylog (если проведены соответствующие настройки в файле .env).
- Логи от логгеров default, scheduler, export, i18n, licence, nbi, org.eclipse.jetty, org.springframework записываются в файлы с соответствующим именем в директории /var/log/eltex-wifi-cab/.
Переменные среды для управления логерами
Переменная среды | Значение по умолчанию |
---|
Файл для переопределения переменных среды |
LOG4J_CONFIGURATION_FILE | /etc/eltex-wifi-cab/log4j2-docker.xml |
Настройки логирования STDOUT |
LOG_LEVEL | DEBUG |
CONSOLE_LEVEL | INFO |
Настройки Graylog |
GELF_LEVEL | OFF |
GELF_HOST | udp:localhost |
GELF_PORT | 12201 |
/var/log/eltex-wifi-cab/default.log |
LOGGER_DEFAULT_LEVEL | OFF |
/var/log/eltex-wifi-cab/scheduler.log |
LOGGER_SCHEDULER_LEVEL | OFF |
/var/log/eltex-wifi-cab/export.log |
LOGGER_EXPORT_LEVEL | OFF |
/var/log/eltex-wifi-cab/i18n.log |
LOGGER_I18N_LEVEL | OFF |
/var/log/eltex-wifi-cab/licence.log |
LOGGER_LICENCE_LEVEL | OFF |
/var/log/eltex-wifi-cab/nbi.log |
LOGGER_NBI_LEVEL | OFF |
/var/log/eltex-wifi-cab/spring.log |
LOGGER_SPRING_LEVEL | OFF |
Логгеры, которые пишут в Root (STDOUT, Gelf) |
LOGGER_QUARTZ_LEVEL | OFF |
LOGGER_MONGODB_DRIVER_LEVEL | INFO |
Помимо указания значений переменных среды непосредственно в файлах "docker-compose.yml" и ".env", существует возможность получить их из файла log4j2-docker.xml. В файле, расположенном в контейнере, значения переменных указаны по умолчанию. Для его переопределения примонтируйте Ваш файл log4j2-docker.xml в директорию в контейнере /etc/eltex-wifi-cab/log4j2-docker.xml через настройки volumes в docker-compose.yml.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="OFF" monitorInterval="600">
<Properties>
<Property name="maxSize" value="10MB"/>
<Property name="maxCount" value="10"/>
<Property name="lastModified" value="7d"/>
<Property name="accumulatedFileSize" value="100 MB"/>
<Property name="logDir" value="/var/log/eltex-wifi-cab"/>
<Property name="defaultPattern" value="%d{ISO8601} [%t] %-5p %logger{1} %C{1}.%M(line:%L). %m%n"/>
<Property name="dateSuffix" value="%d{yyyyMMdd}"/>
<Property name="filenamePrefix" value="eltex-wifi-cab"/>
<Property name="rootLevel">${env:LOG_LEVEL:-INFO}</Property>
<Property name="consoleLevel">${env:CONSOLE_LEVEL:-INFO}</Property>
<Property name="gelfLevel">${env:GELF_LEVEL:-OFF}</Property>
<Property name="gelfHost">${env:GELF_HOST:-udp:localhost}</Property>
<Property name="gelfPort">${env:GELF_PORT:-12201}</Property>
<Property name="loggerDefaultLevel">${env:LOGGER_DEFAULT_LEVEL:-OFF}</Property>
<Property name="loggerSchedulerLevel">${env:LOGGER_SCHEDULER_LEVEL:-OFF}</Property>
<Property name="loggerExportLevel">${env:LOGGER_EXPORT_LEVEL:-OFF}</Property>
<Property name="loggerI18nLevel">${env:LOGGER_I18N_LEVEL:-OFF}</Property>
<Property name="loggerLicenceLevel">${env:LOGGER_LICENCE_LEVEL:-OFF}</Property>
<Property name="loggerQuartzLevel">${env:LOGGER_QUARTZ_LEVEL:-OFF}</Property>
<Property name="loggerMongodbDriverLevel">${env:LOGGER_MONGODB_DRIVER_LEVEL:-INFO}</Property>
<Property name="loggerNbiLevel">${env:LOGGER_NBI_LEVEL:-OFF}</Property>
<Property name="loggerSpringLevel">${env:LOGGER_SPRING_LEVEL:-OFF}</Property>
</Properties>
<Appenders>
<RollingFile name="default" fileName="${logDir}/default.log"
filePattern="${logDir}/default-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="default-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="scheduler" fileName="${logDir}/scheduler.log"
filePattern="${logDir}/scheduler-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="scheduler-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="export" fileName="${logDir}/export.log"
filePattern="${logDir}/export-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="export-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="i18n-log" fileName="${logDir}/i18n.log"
filePattern="${logDir}/i18n-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="i18n-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="licence" fileName="${logDir}/licence.log"
filePattern="${logDir}/licence-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="licence-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="nbi" fileName="${logDir}/nbi.log"
filePattern="${logDir}/nbi-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="nbi-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="spring" fileName="${logDir}/spring.log"
filePattern="${logDir}/spring-${dateSuffix}-%i.log">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
<!-- Правило по размерам файла (например, нарезать новые через каждые 10Мб) -->
<SizeBasedTriggeringPolicy size="${maxSize}"/>
<!-- Ограничение на кол-во файлов. -->
<DefaultRolloverStrategy max="${maxCount}">
<Delete basePath="${logDir}" maxDepth="1">
<IfFileName glob="spring-*.log">
<IfAny>
<IfLastModified age="${lastModified}"/>
<IfAccumulatedFileCount exceeds="${maxCount}"/>
<IfAccumulatedFileSize exceeds="${accumulatedFileSize}"/>
</IfAny>
</IfFileName>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout>
<pattern>${defaultPattern}</pattern>
</PatternLayout>
</Console>
<Gelf name="Gelf"
host="${gelfHost}"
port="${gelfPort}"
version="1.1"
facility="${filenamePrefix}"
extractStackTrace="true"
originHost="%host{fqdn}"
maximumMessageSize="8192">
<Field name="thread" pattern="%t"/>
<Field name="level" pattern="%level"/>
<Field name="severity" pattern="%-5level"/>
<Field name="logger" pattern="%logger{1}"/>
<Field name="location" pattern="%C{1}.%M(line:%L)"/>
</Gelf>
</Appenders>
<Loggers>
<Root level="${rootLevel}">
<AppenderRef ref="console" level="${consoleLevel}"/>
<AppenderRef ref="Gelf" level="${gelfLevel}"/>
</Root>
<Logger name="default">
<AppenderRef ref="default" level="${loggerDefaultLevel}"/>
</Logger>
<Logger name="scheduler" level="${loggerSchedulerLevel}">
<AppenderRef ref="scheduler"/>
</Logger>
<Logger name="export" level="${loggerExportLevel}">
<AppenderRef ref="export"/>
</Logger>
<Logger name="i18n" level="${loggerI18nLevel}">
<AppenderRef ref="i18n-log"/>
</Logger>
<Logger name="licence" level="${loggerLicenceLevel}">
<AppenderRef ref="licence"/>
</Logger>
<Logger name="org.quartz" level="${loggerQuartzLevel}"/>
<Logger name="org.mongodb.driver" level="${loggerMongodbDriverLevel}"/>
<Logger name="nbi" additivity="false" level="${loggerNbiLevel}">
<AppenderRef ref="nbi"/>
</Logger>
<Logger name="org.eclipse.jetty" level="${loggerSpringLevel}">
<AppenderRef ref="spring"/>
</Logger>
<Logger name="org.springframework" level="${loggerSpringLevel}">
<AppenderRef ref="spring"/>
</Logger>
</Loggers>
</Configuration>
Если Вы планируете записывать логи не в файловую систему контейнера, а на хост, то необходимо примонтировать папку, в которой Вы планируете записывать логи, к директории /var/log/eltex-wifi-cab/ в контейнере. Также для этой директории требуется выставить UID=100001, GID=100001 с помощью команды:
sudo mkdir -p /var/log/eltex-wifi-cab && sudo chown -R 100001:100001 /var/log/eltex-wifi-cab