netbox-docker и PostgreSQL 18: база выглядит пустой
АйТи Фреш
Linux, Docker и DevOps

После обновления netbox-docker база выглядит пустой: как пережить переход образа на PostgreSQL 18

Автор: , директор ООО «АйТи-Фреш» · · ~16 мин чтения
Перенос базы данных PostgreSQL из контейнера netbox-docker старой версии в контейнер PostgreSQL 18 через экспорт и импорт
Данные не переезжают сами — их нужно аккуратно перенести дампом между двумя мажорными версиями PostgreSQL.

Обновили netbox-docker, контейнеры поднялись, а в интерфейсе — пустой NetBox без единого устройства? Данные почти наверняка целы: начиная с 4.0.0 netbox-docker перешёл на PostgreSQL 18 и монтирует базу в новый том `netbox-postgres`, а старый `netbox-postgres-data` просто остался в стороне. Показываю, как в этом убедиться и как перенести базу дампом по процедуре из вики проекта.

Почему база «пустая»: netbox-docker сменил том и мажорную версию PostgreSQL

Если вы уже разбирали похожую ситуацию с обычным Docker Compose и образом postgres:18 — обновили тег с 16-го на 18-й, а контейнер поднял базу с нуля, хотя старый именованный том никуда не делся, — вы наверняка узнаёте симптом. Я подробно разбирал этот случай в статье «Обновил образ до postgres:18 — база создаётся заново, хотя старый том на месте»: там причина в том, что официальный образ postgres с 18-й версии изменил переменную PGDATA на версионированный путь и точку монтирования VOLUME, и если ваш docker-compose.yml жёстко указывает старый путь /var/lib/postgresql/data, новый контейнер инициализирует пустой кластер в другом месте, а старые данные остаются нетронутыми, но невидимыми.

С netbox-docker история похожая по симптому, но устроена иначе — и именно с ней мы чаще всего сталкиваемся в проектах внедрения NetBox. Здесь compose-файл за вас уже переписали авторы проекта. До 4.0.0 (например, в релизах 3.2–3.4) сервис postgres работал на образе postgres:17-alpine, а данные лежали в томе netbox-postgres-data, смонтированном в /var/lib/postgresql/data. Начиная с 4.0.0 в docker-compose.yml стоит postgres:18-alpine, том называется уже netbox-postgres и монтируется в /var/lib/postgresql — ровно туда, куда образ 18-й версии перенёс VOLUME, а PGDATA теперь /var/lib/postgresql/18/docker.

Отсюда и «пустая база». После привычных git pull, docker compose pull и docker compose up -d Docker Compose не находит тома <проект>_netbox-postgres, создаёт его пустым, PostgreSQL 18 инициализирует в нём новый кластер, а контейнер NetBox при старте честно прогоняет миграции и получает чистую схему без единого устройства. Никакой ошибки несовместимости в логах при этом нет — новый сервер старые файлы вообще не видит. Старый том <проект>_netbox-postgres-data с кластером PostgreSQL 17 остаётся на диске нетронутым, только к стеку он больше не подключён. Подключить его «как есть» к PostgreSQL 18 тоже нельзя: файлы кластера одной мажорной версии не читаются бинарниками другой, поэтому release notes 4.0.0 и требуют экспорт и повторный импорт базы.

Не удаляйте «лишние» тома после неудачного апдейта netbox-docker: в `<проект>_netbox-postgres-data` лежат все ваши данные, пока вы не сняли с них дамп.
Сравнение двух причин пустой базы после перехода Docker-образа на PostgreSQL 18: свой compose и netbox-docker
Одинаковый симптом «база пустая» — разные механизмы, но в обоих случаях данные целы, пока вы не удалили том.

Что именно требуют релиз-заметки netbox-docker 4.0.0

Релиз netbox-docker 4.0.0 (3 февраля 2026 года) прямым текстом предупреждает: «это мажорное обновление версии образа PostgreSQL. Вам нужно экспортировать и заново импортировать вашу базу данных» — со ссылкой на раздел PostgreSQL Update вики. Там же отдельное предупреждение: в PR #1259 мейнтейнеры официального образа postgres изменили способ монтирования каталога данных, «проверьте свою конфигурацию». Оба фактора работают вместе: смена мажорной версии PostgreSQL требует dump/restore, а смена имени и точки монтирования тома в compose-файле приводит к тому, что без этой процедуры стек молча поднимается на новом пустом томе. Автоматически перенос данных никто за вас не выполнит.

Второе требование релиза 4.0.0 — совместимость по версии NetBox: «эта версия netbox-docker совместима только с NetBox v4.5.x и выше». Если на момент апгрейда у вас установлена более старая версия NetBox (4.4 и ранее), одновременно с переходом на PostgreSQL 18 нужно поднимать и саму версию NetBox — а это уже отдельная тема совместимости схемы и, возможно, мажорного перехода по правилам самого NetBox, если разрыв версий большой. Актуальная ветка release на 23.09.2026 — netbox-docker 5.1.1 (10 сентября 2026), она совместима только с NetBox 4.7.x и новее, а сама NetBox 4.7 требует PostgreSQL 15+ — с PostgreSQL 18 из compose-файла это требование выполняется.

На практике это означает, что апгрейд netbox-docker до 4.0.0 и новее почти никогда не бывает изолированным изменением одного компонента: он тянет за собой минимум два потенциально мажорных перехода сразу — PostgreSQL и, возможно, самого NetBox, если вы отставали по версии дольше пары релизов. Я всегда рассматриваю такие апгрейды как отдельный проект с явным откатным планом, а не как рутинную операцию по расписанию, каких в норме большинство.

Из этого следует практическое правило: перед обновлением netbox-docker до 4.0.0 или новее всегда сверяйте текущую версию NetBox по её собственным требованиям к минорной цепочке апгрейда, и отдельно — планируйте dump/restore PostgreSQL как обязательный шаг, а не как «на всякий случай». Пропуск любого из двух требований и даёт тот самый эффект «пустая база после апгрейда».

Два разных «апдейта», которые путают: миграция схемы NetBox и апгрейд PostgreSQL

В вики netbox-docker раздел Updating чётко разводит два процесса, которые администраторы обычно воспринимают как один и тот же «апдейт». Обычное обновление — когда меняется только версия самого NetBox, а PostgreSQL остаётся прежней мажорной версии — проходит автоматически: команда docker compose up -d поднимает новые контейнеры, и, по формулировке вики, «это также автоматически смигрирует схему базы данных NetBox». Никакого ручного dump/restore для этого не требуется — Django-миграции самого NetBox применяются к базе на лету при старте контейнера, как и в обычной (не Docker) установке.

Апгрейд самой PostgreSQL между мажорными версиями — процесс принципиально другого рода, и он не выполняется автоматически никогда, ни в 4.0.0, ни в любом другом релизе, где меняется мажорная версия образа СУБД. Мажорная версия PostgreSQL меняет внутренний формат файлов кластера, и новый бинарник просто не умеет читать данные, записанные предыдущей мажорной версией, без специальной процедуры конвертации (либо pg_upgrade, либо дамп/восстановление на уровне SQL — в официальной документации netbox-docker используется именно второй, более простой и надёжный для контейнерных инсталляций путь).

Путаница возникает потому, что оба процесса в быту называют одним словом «обновили netbox-docker». Человек видит, что предыдущий десяток обновлений проходил одной командой docker compose pull && docker compose up -d без единой ручной операции — и предполагает, что так будет всегда. Релиз, где меняется мажорная версия PostgreSQL внутри образа, — редкое, но принципиально иное событие, и именно поэтому авторы вынесли его в раздел Noteworthy Changes релиз-заметок — но читают их, как показывает обсуждение #1634 в netbox-docker, далеко не все.

«docker compose up -d и всё само смигрируется» — верно для обычных обновлений NetBox, но не работает для перехода самой PostgreSQL на новую мажорную версию.
Шесть шагов перехода базы netbox-docker с PostgreSQL старой версии на PostgreSQL 18 через dump и restore
Шесть шагов, из которых критичен четвёртый: удалять нужно именно том с данными PostgreSQL, а не весь стек томов netbox-docker.

Процедура перехода: экспорт, замена, импорт

Официальная процедура из раздела PostgreSQL Update вики netbox-docker выполняется до обновления файлов проекта: сначала останавливаете весь стек и поднимаете только контейнер PostgreSQL старой версии, чтобы снять дамп именно с него, работающего:

docker compose down
docker compose up -d postgres
docker compose exec -T postgres sh -c 'pg_dump -cU $POSTGRES_USER $POSTGRES_DB' | gzip > db_dump.sql.gz

После того как дамп снят и вы убедились, что файл не пустой и не оборвался (проверьте размер архива и, если есть возможность, количество строк COPY внутри), вики предлагает удалить том с данными PostgreSQL — не трогая остальные тома netbox-docker (media, reports, scripts). При переходе на 4.0.0 это старый том netbox-postgres-data: новый стек его уже не использует, а восстановление пойдёт в новый том netbox-postgres, который Compose создаст сам. Я этот шаг откладываю до проверки NetBox на новой версии — место на диске старый том занимает недолго, а откатиться с ним проще:

docker compose down
docker volume rm netbox-docker_netbox-postgres-data

Общий принцип — снять рабочую копию перед необратимым шагом, проверить её и только потом двигаться дальше — я закладываю в любой регламент бэкапа баз данных, не только для PostgreSQL под NetBox. Дальше подтягиваете новые файлы репозитория и новый образ (git pull, docker compose pull), поднимаете PostgreSQL уже 18-й версии на пустом томе и восстанавливаете дамп в неё:

docker compose up -d postgres
gunzip -c db_dump.sql.gz | docker compose exec -T postgres sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'
docker compose up -d

Если вы уже успели запустить новый стек и он создал пустой кластер, перед восстановлением удалите именно новый том: docker compose down и docker volume rm netbox-docker_netbox-postgres (имя проекта у вас может отличаться — проверьте docker volume ls), иначе дамп ляжет поверх свежей схемы и восстановление будет сыпать ошибками, как у автора обсуждения #1634. Последняя команда из блока выше поднимает весь остальной стек — и вот здесь уже отрабатывает обычная автомиграция схемы NetBox, если заодно поднимается и новая версия самого NetBox. Два процесса идут друг за другом: сначала вручную мигрируете данные PostgreSQL, потом NetBox автоматически донастраивает схему под свою актуальную версию поверх уже перенесённых данных.

Цифры кейса типографии Литерный двор: восстановление базы NetBox после перехода netbox-docker на PostgreSQL 18
40 минут по официальной процедуре — против риска потерять полтора года накопленной документации сети.

Кейс: типография «Литерный двор», 20 рабочих мест — обновление после года без апдейтов

У типографии «Литерный двор» (20 рабочих мест) NetBox в связке netbox-docker крутился на выделенном сервере около полутора лет без единого обновления — на netbox-docker 3.2.1 с NetBox 4.2 и PostgreSQL 17 — заводили его под учёт сетевого оборудования производственного цеха и офиса, система работала, руки до апдейтов не доходили. Когда решили обновиться разом до актуальной версии, администратор клиента сделал стандартное git pull && docker compose pull && docker compose up -d — так обновлялись раньше, и раньше это всегда срабатывало без сюрпризов.

На этот раз после поднятия контейнеров NetBox открылся, но старый логин не подошёл, а после создания нового суперпользователя списки устройств, IP-адресов и площадок оказались пустыми — ровно то состояние, которое выглядит как катастрофа, если не знать заранее, что произошло. В логах контейнера postgres никаких ошибок не было — только сообщения initdb о создании нового кластера. Зато docker volume ls показал два тома: новый netbox-docker_netbox-postgres, созданный минутами раньше, и старый netbox-docker_netbox-postgres-data. Всё стало понятно: стек поднялся на новом пустом томе.

Старый том с кластером PostgreSQL 17 остался нетронутым. Остановили стек, переключили рабочую копию обратно на тег 3.2.1 (git checkout 3.2.1), подняли только postgres 17 на старом томе, убедились, что данные на месте, и сняли pg_dump. Дальше — процедура выше: вернулись на ветку release, удалили пустой новый том netbox-postgres, подняли postgres 18, восстановили дамп и запустили актуальный стек netbox-docker 5.1.1 с NetBox 4.7.1 — переход 4.2 → 4.7 в пределах одной мажорной ветки NetBox делает автоматически при старте. Все данные — порядка 340 устройств, 60 IP-префиксов и полная схема стоек цеха — вернулись без потерь. Старый том удалили через неделю, когда убедились, что всё работает.

Вся процедура заняла около 40 минут, из которых большая часть — время на снятие и восстановление дампа на их объёме данных. После этого я составил клиенту отдельную памятку: перед любым мажорным обновлением netbox-docker сначала читать раздел релиз-заметок целиком, а не сразу запускать привычную команду по накатанной.

Что я теперь делаю по умолчанию при апдейтах netbox-docker

Перед любым обновлением netbox-docker, особенно если между текущей и целевой версией прошло больше пары месяцев, я в первую очередь открываю не changelog самого NetBox, а именно релиз-заметки netbox-docker на GitHub — там отдельно фиксируются изменения инфраструктурного слоя (версия PostgreSQL, Redis, переменные окружения), которые в changelog NetBox вообще не упоминаются, потому что относятся не к приложению, а к обвязке Docker.

Второе правило — снимать дамп базы перед любым обновлением, где меняется хотя бы один из компонентов инфраструктуры (не только PostgreSQL, но и, например, версия Redis), даже если релиз-заметки явно не требуют dump/restore. Это занимает пару минут на среднем объёме данных, а отсутствие свежего бэкапа перед мажорным изменением — фактор риска, который совершенно не обязательно материализуется, но если материализуется, стоит часов простоя.

Третье — держать отдельно от общего пайплайна апдейтов регулярную проверку версии NetBox и netbox-docker на совместимость: 4.0.0 привязана к NetBox 4.5.x+, и если версии внутри стека расходятся с этим требованием, апгрейд лучше планировать в два шага — сначала довести NetBox до нужной минорной версии в рамках текущего netbox-docker, потом уже переходить на новый netbox-docker с новой PostgreSQL. Тот же подход — не мешать в одной операции апдейт приложения и апгрейд инфраструктурного слоя — я использую и в регламенте эксплуатации Zabbix: там точно так же смешивают обновление самого Zabbix с обновлением базы под ним.

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

Чем этот случай отличается от общей проблемы с PGDATA в образе postgres:18?

Механизм родственный: в netbox-docker 4.0.0 compose-файл сам переключил базу на новый том netbox-postgres с точкой монтирования /var/lib/postgresql и PostgreSQL 18. Старые данные остаются в томе netbox-postgres-data, а подключить их к PostgreSQL 18 напрямую нельзя — нужен dump/restore по вики проекта.

Можно ли просто удалить старый том и начать с чистой базы?

Технически да, NetBox поднимется, но вы потеряете все данные — устройства, IP-адреса, кабельные соединения. Сначала снимите дамп со старого тома netbox-postgres-data (на старой версии netbox-docker и PostgreSQL 17) и только потом удаляйте что-либо.

Обязательно ли обновлять NetBox одновременно с переходом на netbox-docker 4.0.0?

netbox-docker 4.0.0 совместим только с NetBox v4.5.x и новее. Если у вас более старая версия NetBox, её нужно поднять отдельно, желательно до перехода на новый netbox-docker, с учётом собственных правил NetBox по мажорным апгрейдам.

Автомиграция схемы NetBox при docker compose up -d затронет данные PostgreSQL?

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

Как узнать заранее, что апгрейд netbox-docker потребует dump/restore PostgreSQL?

Читайте релиз-заметки конкретной версии netbox-docker на GitHub перед обновлением — такие требования указываются явно, обычно в первых строках описания релиза, как это сделано в 4.0.0.

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

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

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

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

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

Источники

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