Как сохранить конфигурацию Asterisk при перезапуске Docker
Если после перезагрузки хоста телефония не поднялась, сначала проверьте, запущен ли контейнер и видит ли 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 и ждать, что там волшебно окажутся рабочие конфиги. Сначала выясните, что лежит в образе и на хосте, сделайте копию, затем спланируйте перенос и проверку чтения.
- Сохранить compose и сведения о контейнере
- Найти действующие тома и резервные копии
- Не удалять остановленный контейнер до осмотра
Настройте постоянное хранение по фактическим путям
Для постоянных данных 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, ещё не доказал, что его можно вернуть и что вместе с ним вернутся права и рабочие настройки.
Автозапуск и перезапуск решают разные задачи
В 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-ы, доступны ли тестовый маршрут и очередь, появляются ли ожидаемые записи в журналах. Алерт должен сообщать о неисправности человеку, а автоматическое действие — иметь понятное условие, ограничение повторов и проверку результата. Иначе автоматика просто быстрее повторяет ту же ошибку.
- Проверить политику рестарта контейнера
- Проверить автозапуск Docker Engine
- Планировать перезапуск Asterisk с учётом активных вызовов
Проверьте звонок, журналы и восстановление
Начните с версии именно запущенного экземпляра: выполните команду 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, какие тома нельзя удалять, как откатить образ и как проверить доступность после запуска. Это короткая инструкция, которая в аварии ценнее длинного отчёта о том, кто нажал не ту кнопку.
- Уточнить образ и версию запущенного контейнера
- Проверить звонок и двусторонний звук
- Сопоставить queue_log, CDR и журналы запуска
- Проверить восстановление из резервной копии
Частые вопросы
Стирает ли перезапуск Docker данные контейнера?
Сам по себе останов/перезапуск сохраняет существующий контейнер и его writable layer. При удалении контейнера этот слой теряется; тома живут отдельно, если их не удалить отдельно.
Что вынести в том Asterisk?
Определите по конкретному образу, где находятся используемые конфиги, данные и журналы, затем вынесите нужные каталоги. Типичные пути — ориентиры, а не гарантия для любой сборки.
Можно ли использовать core restart when convenient без обрыва звонков?
Команда ждёт отсутствия активных вызовов, но не блокирует новые. Поэтому ожидание может затянуться; отсутствие перерыва не гарантируется.
Что означает ABANDON в queue_log?
Вызывающий покинул очередь до соединения. Событие содержит позицию и время ожидания, но не объясняет причину потери связи.
Поможет ли restart: unless-stopped при перезагрузке хоста?
Политика просит Docker запускать контейнер после старта демона, если контейнер не был остановлен вручную. Она не исправляет ошибку конфигурации и не заменяет проверку Docker Engine.
Источники
- Docker Docs — Volumes — Жизненный цикл томов, хранение данных вне контейнера и влияние mount на содержимое каталога. https://docs.docker.com/engine/storage/volumes/
- Docker Docs — Storage — Слой контейнера, volumes, bind mounts и tmpfs. https://docs.docker.com/engine/storage/
- Docker Docs — Restart policies — Поведение политик автоматического запуска контейнеров. https://docs.docker.com/engine/containers/start-containers-automatically/
- Asterisk Documentation — Queue Logs — Путь queue_log и значение события ABANDON. https://docs.asterisk.org/Operation/Logging/Queue-Logs/
- Asterisk Documentation — Stopping and Restarting — Различия core restart now, gracefully и when convenient. https://docs.asterisk.org/Operation/Running-Asterisk/Stopping-and-Restarting-Asterisk-From-The-CLI/



