Asterisk в Docker: почему после перезагрузки нет звонков
АйТи Фреш
Linux, Docker и DevOps

Как сохранить конфигурацию Asterisk при перезапуске Docker

Автор: , директор ООО «АйТи-Фреш» · · ~11 мин чтения
Схема маршрутизации и отдельная карточка хранения показывают разницу между перезапуском и удалением контейнера
Контейнер перезапустился — данные остались или нет?

Если после перезагрузки хоста телефония не поднялась, сначала проверьте, запущен ли контейнер и видит ли Asterisk прежнюю конфигурацию. Сам по себе перезапуск контейнера не стирает его файловую систему; потеря данных обычно связана с удалением контейнера без постоянного тома или с неверным путём монтирования. Ниже — порядок проверки.

Сначала выясните, что именно произошло с контейнером

Я не называю любой сбой после reboot потерей файлов. У Docker есть writable layer — записываемый слой конкретного контейнера. Остановка контейнера или перезапуск хоста сами по себе не равны удалению этого контейнера: если тот же контейнер сохранился, его слой тоже сохраняется. Данные из этого слоя теряются, когда контейнер удаляют и создают новый. И вот здесь отсутствие volume становится проблемой: новый контейнер стартует из образа, а ручные изменения старого слоя к образу не приклеены. Docker не ясновидящий и не переносит их за вас.

Разделите симптомы. Если контейнер не запущен, проверьте список всех контейнеров, их статус, код завершения и журнал запуска. Если контейнер работает, но абоненты не зарегистрированы, проверьте, какой конфигурационный каталог он читает, какие файлы доступны и не стартовал ли он с настройками из образа. Если регистрация есть, но разговоры без звука, исследуйте SIP-сигнализацию, адреса и RTP-маршрут: пустой звук не доказывает потерю конфигурации. Один симптом — ещё не диагноз, как бы ни хотелось сразу переписать compose.

После перезагрузки хоста Docker обычно возвращает существующий контейнер к работе только при настроенной политике рестарта и запущенном Docker Engine. Если compose-проект при обслуживании был разобран с удалением контейнеров, это уже другой сценарий. Посмотрите docker compose ps -a, журнал контейнера и параметры сервиса в compose-файле; затем сравните имя/идентификатор контейнера и фактически подключённые mount-ы. Не запускайте подряд down, up и очистку томов, пока не поняли, где лежит единственная копия конфигурации. Команда «на всякий случай» умеет сделать аварию аккуратнее, но не короче.

Перезапуск контейнера сохраняет его слой; удаление контейнера удаляет этот слой.
Разница между остановкой существующего контейнера, его удалением и сохранением тома
Остановка сохраняет слой; удаление — нет.

Условный пример: настройки исчезли после пересоздания

Возьму условный пример из поля company — «Лагуна-Строй». Это схема диагностики, а не опубликованный кейс с заявленными сроками и результатами. После обновления хоста сотрудники не могут звонить. Проверка показывает: старый контейнер удалён, новый создан из образа, а файлы конфигурации не были вынесены в постоянный том. Значит, восстановить именно прежние настройки из нового контейнера может быть неоткуда. Событие ABANDON в queue_log здесь не поможет: оно описывает звонящего, который покинул очередь до соединения, а не причину, по которой исчезла конфигурация.

До любых изменений я сохраняю то, что ещё доступно: compose-файл, вывод docker inspect по контейнеру, журналы Docker и Asterisk, список томов, а также копию текущих файлов. Если старый контейнер остановлен, но не удалён, его файловую систему ещё можно осмотреть и экспортировать. Если он уже удалён, проверяю named volumes, резервные копии и хостовые каталоги. Не обещаю восстановить удалённые данные без копии; сначала устанавливаю, существует ли источник. Иначе совет «сейчас всё скопируем» — просто бодрая формулировка отсутствия плана.

Я также проверяю, не закрывает ли новый mount содержимое каталога, которое раньше приходило из образа. При подключении непустого тома к уже заполненному пути его содержимое становится видимым поверх файлов контейнера; исходные файлы за mount не видны, пока он подключён. Поэтому новый том нельзя монтировать вслепую на /etc/asterisk и ждать, что там волшебно окажутся рабочие конфиги. Сначала выясните, что лежит в образе и на хосте, сделайте копию, затем спланируйте перенос и проверку чтения.

«Лагуна-Строй» здесь — условный пример; реальные результаты и сроки не заявляю.

Настройте постоянное хранение по фактическим путям

Для постоянных данных Asterisk обычно рассматривают конфигурацию, рабочие данные и журналы, но конкретный набор путей зависит от образа, сборки и способа настройки. В типичной установке встречаются /etc/asterisk, /var/lib/asterisk и /var/log/asterisk; это ориентиры для проверки, а не универсальный контракт любого Docker-образа. Путь для журналов очереди по умолчанию — /var/log/asterisk/queue_log, но logging может быть перенастроен. Я сначала проверяю конфигурацию образа и фактические mount-ы, а затем решаю, какие каталоги вынести в named volumes или bind mounts.

В compose можно описать bind mount, например ./asterisk-data:/var/lib/asterisk, либо именованный том. Bind mount связывает конкретный путь хоста с каталогом контейнера, поэтому расположение данных проще увидеть и включить в резервное копирование. Именованный том хранит данные вне жизненного цикла контейнера и управляется Docker; его содержимое не следует удалять командами очистки, пока не проверен состав томов и политика хранения. Важно сопоставлять источник и точку назначения: если каталог на хосте пустой, приложение может увидеть пустое содержимое, а не прежние файлы внутри контейнера.

Не монтируйте весь /etc/asterisk только потому, что в примере из блога так написано. Убедитесь, что там есть полный согласованный комплект файлов, включая нужные модулям настройки, а не один частичный конфиг. И не выносите /tmp «для сохранения RTP»: RTP — сетевой медиапоток, а утверждение, что Asterisk по умолчанию кэширует его в /tmp, я удалил как неподтверждённое. Временный каталог монтируют отдельно лишь при конкретной потребности образа или приложения. Для звука проверяют настройки RTP и сетевую публикацию UDP-портов согласно выбранной конфигурации.

Права доступа проверяйте изнутри контейнера: выясните, от какого UID/GID работает процесс Asterisk, какие каталоги он должен читать и куда писать, затем сравните владельца и режимы на хосте. Универсальный chown -R asterisk:asterisk /opt/asterisk опасен как рецепт: пользователь asterisk на хосте может отсутствовать, образ может запускать процесс под другим UID, а бездумная рекурсия меняет владельцев лишних файлов. При Permission denied сначала смотрите точный путь и UID процесса; исправляйте только нужный каталог и по документации конкретного образа.

Для защиты от отказа диска тома не заменяют резервную копию: volume на том же хосте исчезнет вместе с повреждённым диском или ошибочным удалением. Определите, что именно нужно восстановить — конфигурацию, базу CDR, записи разговоров, если они включены, и прочие данные — и делайте резервные копии в отдельное место. Периодически проверьте восстановление на тестовом экземпляре. Файл, который однажды записался в каталог backup, ещё не доказал, что его можно вернуть и что вместе с ним вернутся права и рабочие настройки.

Сверьте пути и UID/GID с конкретным образом до переноса данных.
Если хотите проверить такую схему на своей телефонии, мы разберём конфигурацию образа, расположение данных и порядок восстановления. Начинаем с того, что уже запущено: без догадок о путях и без обещаний восстановить данные, если копии нет. Обсудить задачу
Порядок проверки путей, прав и резервного восстановления данных Asterisk
Сначала образ, пути и права доступа.

Автозапуск и перезапуск решают разные задачи

В Compose параметр restart: unless-stopped просит Docker запускать контейнер после выхода процесса и при старте демона, если администратор не остановил его вручную. restart: always близок по смыслу, но отличается поведением после ручной остановки и старта Docker. Это не проверка здоровья Asterisk и не ремонт конфигурации: если процесс завершился с ошибкой, политика может снова поднять тот же неисправный контейнер. Смотрите реальные статусы и журналы, а не объявляйте повторы рестарта «лечением».

Проверьте также, включён ли Docker Engine при загрузке хоста и не ждёт ли сам контейнер зависимости, которая ещё не готова. Автоматический старт Docker и политика restart — связанные, но разные настройки. Убедитесь, что compose-проект использует нужный файл и профиль, иначе администратор может проверять одну конфигурацию, а запускаться будет другая. Я предпочитаю проверить это контролируемой перезагрузкой на стенде: зафиксировать статус до и после, убедиться в подключении томов и выполнить тестовый вызов. В рабочее время такую проверку назначают с учётом влияния на телефонию.

Перезапуск самого Asterisk внутри CLI тоже не равен перезапуску контейнера. Команда core restart now завершает текущие вызовы; core restart gracefully прекращает принимать новые и ждёт окончания активных; core restart when convenient ждёт, пока активных вызовов не останется, но новые вызовы могут поступать, поэтому ожидание способно затянуться. Команда не гарантирует отсутствие перерыва и не спасает от бесконечного вызова. Для обновления конфигурации сначала проверьте, достаточно ли штатного reload нужного модуля; рестарт планируйте, когда он действительно нужен.

Не подменяйте мониторинг таймером «перезапускать раз в пять минут». Такой скрипт способен обрывать разговоры, скрывать первичную ошибку и создавать повторный сбой. Отдельно контролируйте состояние контейнера и прикладную доступность телефонии: зарегистрированы ли нужные endpoint-ы, доступны ли тестовый маршрут и очередь, появляются ли ожидаемые записи в журналах. Алерт должен сообщать о неисправности человеку, а автоматическое действие — иметь понятное условие, ограничение повторов и проверку результата. Иначе автоматика просто быстрее повторяет ту же ошибку.

Политика рестарта запускает контейнер; она не исправляет причину его падения.

Проверьте звонок, журналы и восстановление

Начните с версии именно запущенного экземпляра: выполните команду CLI внутри нужного контейнера или используйте способ, указанный автором образа. Команда docker run --rm andrius/asterisk:latest asterisk -V из черновика запускает новый контейнер из конкретного стороннего образа, а не проверяет гарантированно уже работающую телефонию. Её убрал из универсальной инструкции. Тег latest также не фиксирует версию для повторяемой проверки. Сначала установите имя образа, tag/digest и имя контейнера из своего compose-проекта.

После запуска проверьте не только docker compose ps, но и сам сценарий звонка: регистрацию нужного endpoint-а, исходящий и входящий тестовый вызов, двусторонний звук и ожидаемое завершение. Если проблема только в RTP, сверяйте диапазон UDP в конфигурации Asterisk, публикацию портов Docker, firewall и сетевую схему. Одного совпадения чисел в двух файлах мало: важны адреса, NAT и путь пакета в обе стороны. Проверяйте соответствие реальному образу и топологии, а не копируйте чужой диапазон как универсальный рецепт.

Если используется очередь, смотрите queue_log. Документация Asterisk определяет ABANDON(position|origposition|waittime) как уход вызывающего из очереди до соединения и указывает стандартное расположение /var/log/asterisk/queue_log. Это запись о судьбе вызова в очереди, а не журнал всех пропущенных звонков и не доказательство, что вызов оборвался при перезагрузке. Для CDR отдельно проверьте включённый backend, его настройки и место записи: пустой CDR сам по себе не говорит, что виноват mount. Сопоставьте время события с журналом Asterisk и Docker.

Закройте проверку не обещанием «теперь не пропадёт никогда», а проверяемым восстановлением. Сохраните копию compose-конфигурации, документируйте тома и точки назначения, затем на тестовом экземпляре восстановите файлы из резервной копии и выполните несколько контрольных звонков. Зафиксируйте, какие данные ожидаете увидеть после пересоздания контейнера. После этого согласуйте процедуру обновления: что делать перед compose down, какие тома нельзя удалять, как откатить образ и как проверить доступность после запуска. Это короткая инструкция, которая в аварии ценнее длинного отчёта о том, кто нажал не ту кнопку.

ABANDON означает уход абонента из очереди; это не универсальный код обрыва.
Алгоритм первичной диагностики Asterisk после перезагрузки хоста
Проверьте запуск, конфигурацию и тестовый звонок.

Частые вопросы

Стирает ли перезапуск Docker данные контейнера?

Сам по себе останов/перезапуск сохраняет существующий контейнер и его writable layer. При удалении контейнера этот слой теряется; тома живут отдельно, если их не удалить отдельно.

Что вынести в том Asterisk?

Определите по конкретному образу, где находятся используемые конфиги, данные и журналы, затем вынесите нужные каталоги. Типичные пути — ориентиры, а не гарантия для любой сборки.

Можно ли использовать core restart when convenient без обрыва звонков?

Команда ждёт отсутствия активных вызовов, но не блокирует новые. Поэтому ожидание может затянуться; отсутствие перерыва не гарантируется.

Что означает ABANDON в queue_log?

Вызывающий покинул очередь до соединения. Событие содержит позицию и время ожидания, но не объясняет причину потери связи.

Поможет ли restart: unless-stopped при перезагрузке хоста?

Политика просит Docker запускать контейнер после старта демона, если контейнер не был остановлен вручную. Она не исправляет ошибку конфигурации и не заменяет проверку Docker Engine.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи