Как обновить GLPI в Docker между версиями

Продакшен-сценарий обновления GLPI в Docker между minor- и major-версиями: матрица решений, согласованный бэкап, миграция схемы, отрепетированный откат и реальные ловушки (потерянный config_db, OPcache, несовместимый плагин), которые приводят к простою.

В этой статьеРазделов: 6

Обновить GLPI в Docker кажется тривиальным — сменить тег образа и поднять контейнер, — но именно эта кажущаяся простота и приводит к незапланированному простою. В сопровождении клиентских сред большинство инцидентов при обновлении связано не с самой миграцией базы данных, а с несовместимыми плагинами, PHP, встроенным в новый образ, или неправильно смонтированным томом, из-за которого GLPI теряет настройки подключения к базе. В этом руководстве собран сценарий, который мы применяем в продакшене, с указанием мест, где всё действительно ломается.

Прежде чем трогать контейнеры: инвентаризация совместимости

Обновление GLPI — это не только образ. Есть три слоя, которые должны обновляться вместе: ядро, плагины и схема базы данных. Классическая ошибка — обновить образ и уже при лежащем сайте обнаружить, что у критичного плагина (например, нативной инвентаризации, SSO или кастомизации полей) нет версии для нового ядра. Выясните заранее:

  • Точные исходная и целевая версии — minor-переход (10.0.15 на 10.0.18) безопасен; major-переход (10.x на 11.x) меняет требования к PHP и может отправить плагины на покой.
  • Матрица плагинов — для каждого установленного плагина убедиться, что есть релиз, совместимый с целевой версией. Плагин без совместимой версии = бизнес-решение (отключить, заменить или отложить обновление), а не сюрприз в 2 часа ночи.
  • PHP, встроенный в образ — официальный образ уже содержит нужный PHP, но если вы используете собственный образ (Alpine + php-fpm), GLPI 11 требует PHP 8.2+. Новое ядро на старом PHP даёт белый экран без внятного лога.
  • Место на диске — дамп и tar томов могут временно удвоить занятое место. Проверьте до, а не во время.

Матрица решений: minor, major или пропуск версий

Тип перехода определяет сценарий. Вот матрица, по которой мы оцениваем окно и риск:

СценарийПримерРискТипичное окноГлавное, на что смотреть
Patch/minor10.0.15 → 10.0.18Низкий5–15 минЛёгкая миграция схемы; плагины обычно продолжают работать
Major10.0.x → 11.0.xВысокий30–90 минPHP, плагины и изменения поведения; сначала протестировать
Пропуск major-версий9.5.x → 11.0.xОчень высокийПланировать поэтапноНЕ пропускать; мигрировать 9.5 → 10.0 → 11.0 по шагам

Частая ошибка — думать, что пропуск версий экономит время. GLPI не гарантирует миграцию схемы через целую major-версию; процедура db:update ожидает структуру непосредственно предыдущей версии. Прыжок с 9.5 сразу на 11 обычно обрывает миграцию на середине, оставляя базу в несогласованном состоянии, — и тогда откат перестаёт быть опцией.

Пошаговое обновление

1. Согласованный бэкап (база + тома)

Бэкап — это не только дамп. Это дамп базы плюс tar томов с файлами (загрузки, документы, кэш плагинов). Оба должны относиться к одному моменту — поэтому мы сначала останавливаем приложение, оставляя работать только базу для дампа:

# Stop the app, keep the database running
docker compose stop glpi-app

# Database dump (dedicated user, password via environment variable)
docker exec glpi-db sh -c 'mysqldump --single-transaction \
  -u glpi -p"${MYSQL_PASSWORD}" glpi' | gzip > /backup/pre-update-$(date +%F).sql.gz

# Tar of the GLPI file volumes
tar -czf /backup/pre-update-files-$(date +%F).tar.gz \
  /var/lib/docker/volumes/glpi_files/_data

--single-transaction гарантирует согласованный дамп без блокировки таблиц InnoDB. И никогда не указывайте пароль в командной строке открытым текстом: он утечёт в историю shell и в docker inspect.

2. Зафиксировать целевую версию в compose

Никогда не используйте тег latest в продакшене. Он без предупреждения смещает цель и делает детерминированный откат невозможным. Зафиксируйте точную версию:

# docker-compose.yml
services:
  glpi-app:
    # From:
    image: glpi/glpi:10.0.18
    # To (exact target version, never :latest):
    image: glpi/glpi:11.0.1
    volumes:
      - glpi_files:/var/glpi/files
      - glpi_config:/var/glpi/config   # config_db.php lives here - do NOT lose it

3. Поднять новый образ

docker compose pull glpi-app
docker compose up -d glpi-app

4. Запустить миграцию схемы

Команда миграции меняла название между поколениями GLPI. Прежде чем запускать вслепую, проверьте, какая команда доступна:

# GLPI 10/11 (Symfony console):
docker exec -u www-data glpi-app php bin/console db:update --no-interaction

# Older GLPI (early 10.0) used:
# docker exec -u www-data glpi-app php bin/console glpi:database:update --no-interaction

Всегда запускайте от пользователя веб-сервера (www-data или apache), никогда от root. Миграция от root создаёт файлы кэша с неправильным владельцем, и затем GLPI начинает выдавать ошибки прав доступа — ложное «сломалось при обновлении», которое на деле просто ownership.

5. Очистить кэш и проверить

docker exec -u www-data glpi-app php bin/console cache:clear
  • Откройте интерфейс и проверьте версию в Настройки > Общие.
  • Запустите внутреннюю диагностику в Настройки > Проверки (проверяет PHP, расширения и права).
  • Убедитесь, что критичные плагины отображаются как активные, а не как «требует обновления».
  • Проверьте реальный сценарий: создать заявку, приложить документ, отправить уведомление.

Чему мы научились, делая это для клиентов

В сопровождении чаще всего повторяется не сбой миграции, а ситуация, когда миграция кажется успешной, а GLPI поднимается с пустой базой по умолчанию. Причина почти всегда одна: том, где хранится config/config_db.php, не смонтирован или смонтирован по другому пути в новой версии. GLPI не находит настройки базы, считает установку чистой и показывает мастер установки. Кто торопится, нажимает «установить» и создаёт новую базу поверх — теперь к простою добавляется риск потери данных. Поэтому в нашем чек-листе первая проверка после запуска — не версия, а то, что docker exec glpi-app cat /var/glpi/config/config_db.php возвращает реальную конфигурацию клиента. Если появился мастер, мы всё останавливаем до любого клика и пересматриваем монтирование томов — никогда не продолжаем через интерфейс.

Второй типичный сценарий — OPcache отдаёт старый код после обновления. Образ сменился, код на диске новый, но php-fpm всё ещё держит в памяти скомпилированную старую версию. Симптом: ошибки несуществующего метода или версия ядра, не совпадающая с образом. Помогает пересоздание контейнера (а не просто перезапуск), потому что процесс php-fpm инициализируется с нуля.

План отката (отрепетированный, а не импровизированный)

Откат надёжен, только если он продуман заранее. С дампом и tar из шага 1 возврат детерминирован:

# Tear down the new version
docker compose down

# Restore the database from the dump
gunzip < /backup/pre-update-2026-07-02.sql.gz \
  | docker exec -i glpi-db sh -c 'mysql -u glpi -p"${MYSQL_PASSWORD}" glpi'

# Revert the image tag in docker-compose.yml to the previous version
# (e.g. glpi/glpi:11.0.1 back to glpi/glpi:10.0.18)

docker compose up -d

Критический момент отката — схема. После того как db:update изменил структуру, база больше не совместима со старым образом. Поэтому откат обязан восстанавливать дамп — вернуть тег недостаточно. Если восстановить только образ при уже мигрированной схеме, старый GLPI будет читать таблицы с «будущей» структурой, что порождает тихие и трудно отслеживаемые ошибки.

Как обойтись без незапланированного простоя

Если среда критичная, окно обновления нужно отрепетировать в тестовой среде на клоне продакшен-базы. Именно там без давления выясняется, ломается ли какой-то плагин и не дольше ли миграция согласованного окна. Обновлять сразу в продакшене без такой репетиции — значит ставить доступность сервиса клиента на удачу.

Если у вашей команды нет окна, чтобы репетировать каждое обновление, или обновление уже однажды растянулось на всю ночь, NexTool берёт на себя сопровождение и обновления вашего GLPI с отрепетированным откатом и согласованным окном. Обратитесь к нам по поводу поддержки и сопровождения GLPI.


Проверено командой NexTool Solutions.

Часто задаваемые вопросы

Остановите приложение (оставив базу работать), сделайте дамп с --single-transaction и tar томов с файлами в один и тот же момент, зафиксируйте точную версию образа в docker-compose.yml (никогда :latest), поднимите контейнер и запустите php bin/console db:update --no-interaction от www-data. Потеря данных почти всегда вызвана неправильно смонтированным томом, а не самой миграцией.

Нет. Процедура db:update ожидает структуру непосредственно предыдущей версии. Пропуск целой major-версии обрывает миграцию на середине и оставляет базу в несогласованном состоянии. Безопасный путь — мигрировать по шагам: 9.5 на 10.0, проверить, затем 10.0 на 11.0.

Зависит от перехода. Patch или minor (например, 10.0.15 на 10.0.18) обычно занимает 5–15 минут. Major-обновление (10.x на 11.x) занимает 30–90 минут, включая бэкап, миграцию и проверку, и его нужно заранее отрепетировать в тестовой среде.

Контейнер не нашёл config/config_db.php — обычно потому, что том с настройками базы не смонтирован или в новом образе изменился его путь. Не нажимайте «установить» (это создаст пустую базу поверх). Остановите всё, исправьте монтирование тома config и поднимите снова.

Остановите контейнеры, восстановите дамп базы, сделанный до обновления, и верните в docker-compose.yml тег образа предыдущей версии. Восстанавливать дамп обязательно: после того как db:update изменил схему, старый образ уже не совместим с мигрированной структурой, поэтому простой возврат тега приводит к тихим ошибкам.

Нет, наоборот. Всегда запускайте от пользователя веб-сервера (www-data или apache). Запуск db:update от root создаёт файлы кэша с неправильным владельцем, и затем GLPI начинает выдавать ошибки прав доступа — ложная тревога «сломалось при обновлении», которая на деле просто ownership.

Нужна помощь?