Cómo Actualizar GLPI en Docker Entre Versiones

Procedimiento de producción para actualizar GLPI en Docker entre versiones menores y mayores: matriz de decisión, copia de seguridad consistente, migración de esquema, rollback ensayado y las trampas reales (config_db perdido, OPcache, plugin incompatible) que causan downtime.

Actualizar GLPI en Docker parece trivial - cambiar la etiqueta de la imagen y levantar el contenedor - pero es justo esa aparente simplicidad la que genera downtime no planificado. En el mantenimiento de entornos de clientes, la mayoría de los incidentes de actualización no vienen de la migración de la base de datos en sí, sino de plugins incompatibles, del PHP embebido en la imagen nueva o de un volumen mal mapeado que hace que GLPI pierda la configuración de base de datos. Esta guía consolida el procedimiento que aplicamos en producción, con los puntos donde las cosas realmente se rompen.

Antes de tocar cualquier contenedor: el inventario de compatibilidad

Una actualización de GLPI no es solo la imagen. Son tres capas que deben subir juntas: el núcleo, los plugins y el esquema de la base de datos. El error clásico es actualizar la imagen y descubrir, con el sitio caído, que un plugin crítico (por ejemplo el de inventario nativo, un SSO o un campo personalizado) no tiene versión para el nuevo núcleo. Verifique esto primero:

  • Versiones exactas de origen y destino - un salto menor (10.0.15 a 10.0.18) es seguro; un salto mayor (10.x a 11.x) cambia el requisito de PHP y puede retirar plugins.
  • Matriz de plugins - para cada plugin instalado, confirmar que existe una versión compatible con el destino. Un plugin sin versión compatible es una decisión de negocio (desactivar, sustituir o posponer la actualización), nunca una sorpresa a las 2 de la madrugada.
  • PHP embebido en la imagen - la imagen oficial ya trae el PHP correcto, pero si usa una imagen propia (Alpine + php-fpm), GLPI 11 exige PHP 8.2+. Un núcleo nuevo sobre PHP viejo da pantalla en blanco sin log claro.
  • Espacio en disco - el dump y el tar de volúmenes pueden duplicar temporalmente el uso. Verifique antes, no durante.

Matriz de decisión: menor, mayor o saltar versiones

El tipo de salto define el procedimiento. Esta es la matriz que usamos para dimensionar ventana y riesgo:

EscenarioEjemploRiesgoVentana típicaCuidado principal
Parche/menor10.0.15 → 10.0.18Bajo5 a 15 minMigración de esquema ligera; los plugins suelen seguir
Mayor10.0.x → 11.0.xAlto30 a 90 minPHP, plugins y cambios de comportamiento; homologar antes
Saltar mayores9.5.x → 11.0.xMuy altoPlanificar por etapasNO saltar; migrar 9.5 → 10.0 → 11.0 en saltos

El error común aquí es creer que saltar versiones ahorra tiempo. GLPI no garantiza la migración de esquema saltando un mayor completo; la rutina db:update espera la estructura de la versión inmediatamente anterior. Saltar de 9.5 directo a 11 suele detener la migración a la mitad, con la base de datos en estado inconsistente - y ahí el rollback deja de ser opcional.

Paso a paso de la actualización

1. Copia de seguridad consistente (base de datos + volúmenes)

Una copia no es solo el dump. Es el dump de la base más el tar de los volúmenes de archivos (subidas, documentos, caché de plugins). Ambos deben ser del mismo instante - por eso paramos la aplicación primero, manteniendo solo la base en pie para el dump:

# Detiene la app, mantiene la base de datos en pie
docker compose stop glpi-app

# Dump de la base (usuario dedicado, contraseña vía variable de entorno)
docker exec glpi-db sh -c 'mysqldump --single-transaction \
  -u glpi -p"${MYSQL_PASSWORD}" glpi' | gzip > /backup/pre-update-$(date +%F).sql.gz

# Tar de los volúmenes de archivos de GLPI
tar -czf /backup/pre-update-files-$(date +%F).tar.gz \
  /var/lib/docker/volumes/glpi_files/_data

--single-transaction genera un dump coherente sin bloquear las tablas InnoDB. Y jamás ponga la contraseña literal en la línea de comandos: se filtra en el historial del shell y en docker inspect.

2. Fijar la versión de destino en el compose

Nunca use la etiqueta latest en producción. Mueve el objetivo sin aviso e impide un rollback determinista. Fije la versión exacta:

# docker-compose.yml
services:
  glpi-app:
    # De:
    image: glpi/glpi:10.0.18
    # A (versión exacta de destino, nunca :latest):
    image: glpi/glpi:11.0.1
    volumes:
      - glpi_files:/var/glpi/files
      - glpi_config:/var/glpi/config   # config_db.php vive aquí - NO perderlo

3. Levantar la nueva imagen

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

4. Ejecutar la migración de esquema

El comando de migración cambió de nombre entre generaciones de GLPI. Confirme qué binario está disponible antes de ejecutar a ciegas:

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

# GLPI más antiguo (10.0 inicial) usaba:
# docker exec -u www-data glpi-app php bin/console glpi:database:update --no-interaction

Ejecute siempre como el usuario del servidor web (www-data o apache), nunca como root. Ejecutar la migración como root crea archivos de caché con dueño incorrecto, y GLPI empieza a dar error de permisos después - un falso "se rompió en la actualización" que es solo propiedad de archivos.

5. Limpiar caché y validar

docker exec -u www-data glpi-app php bin/console cache:clear
  • Acceda a la interfaz y verifique la versión en Configuración > General.
  • Ejecute el diagnóstico interno en Configuración > Verificaciones (PHP, extensiones y permisos).
  • Confirme que los plugins críticos aparecen como activos, no como "necesita actualizar".
  • Pruebe un flujo real: abrir un ticket, adjuntar un documento, disparar una notificación.

Lo que aprendimos operando esto para clientes

En el mantenimiento, el incidente que más se repite no es que la migración falle - es que la migración parezca haber salido bien y GLPI suba con la base predeterminada vacía. La causa casi siempre es la misma: el volumen que guarda config/config_db.php no se mapeó, o se mapeó a una ruta diferente en la versión nueva. GLPI no encuentra la configuración de base de datos, asume que es una instalación limpia y muestra el asistente de instalación. Quien tiene prisa hace clic en "instalar" y crea una base nueva encima - ahora, además del downtime, hay riesgo de pérdida de datos. Por eso, en nuestra checklist, la primera validación post-arranque no es la versión: es que docker exec glpi-app cat /var/glpi/config/config_db.php devuelva la configuración real del cliente. Si aparece el asistente, paramos todo antes de cualquier clic y revisamos el mapeo del volumen - nunca seguimos por la interfaz.

El segundo patrón es el caché de OPcache sirviendo código antiguo tras la actualización. La imagen cambió, el código en disco es nuevo, pero php-fpm todavía tiene la versión antigua compilada en memoria. Síntoma: errores de método inexistente o versión del núcleo que no coincide con la imagen. Recrear el contenedor (y no solo reiniciarlo) lo resuelve, porque el proceso de php-fpm se reinicializa desde cero.

Plan de rollback (ensayado, no improvisado)

Un rollback solo es fiable si se pensó antes. Con el dump y el tar del paso 1, el retorno es determinista:

# Baja la versión nueva
docker compose down

# Restaura la base desde el dump
gunzip < /backup/pre-update-2026-07-02.sql.gz \
  | docker exec -i glpi-db sh -c 'mysql -u glpi -p"${MYSQL_PASSWORD}" glpi'

# Revierte la etiqueta de la imagen en docker-compose.yml a la versión anterior
# (ej.: glpi/glpi:11.0.1 de vuelta a glpi/glpi:10.0.18)

docker compose up -d

Punto crítico del rollback: el esquema. Después de que db:update alteró la estructura, la base ya no es compatible con la imagen antigua. Por eso el rollback tiene que restaurar el dump - no basta con volver la etiqueta. Restaurar solo la imagen, con el esquema ya migrado, deja al GLPI antiguo leyendo tablas de estructura futura, lo que genera errores silenciosos y difíciles de rastrear.

Hacerlo sin downtime no planificado

Si el entorno es crítico, la ventana debe ensayarse en homologación con un clon de la base de producción. Es allí donde se descubre, sin presión, si un plugin se rompe o si la migración tarda más que la ventana acordada. Actualizar directo en producción sin ese ensayo es apostar la disponibilidad del cliente a la suerte.

Si su equipo no tiene ventana para ensayar cada actualización, o ya sufrió una actualización que se volvió madrugada, NexTool se encarga del mantenimiento y las actualizaciones de su GLPI con rollback ensayado y ventana acordada. Hable con nosotros sobre soporte y mantenimiento de GLPI.


Este contenido fue producido con ayuda de inteligencia artificial y revisado por el equipo de Nextool Solutions.

Preguntas Frecuentes

Detenga la aplicación (manteniendo la base de datos en pie), haga el dump con --single-transaction y el tar de los volúmenes de archivos en el mismo instante, fije la versión exacta de la imagen en docker-compose.yml (nunca :latest), levante el contenedor y ejecute php bin/console db:update --no-interaction como www-data. La pérdida de datos casi siempre viene de un volumen mal mapeado, no de la migración en sí.

No. La rutina db:update espera la estructura de la versión inmediatamente anterior. Saltar un mayor completo detiene la migración a la mitad y deja la base inconsistente. El camino seguro es migrar en saltos: 9.5 a 10.0, validar, luego 10.0 a 11.0.

Depende del salto. Un parche o menor (ej.: 10.0.15 a 10.0.18) suele tardar de 5 a 15 minutos. Una actualización mayor (10.x a 11.x) tarda de 30 a 90 minutos incluyendo copia, migración y validación, y debe ensayarse antes en homologación.

El contenedor no encontró config/config_db.php - normalmente porque el volumen que guarda la configuración de base de datos no se mapeó o cambió de ruta en la imagen nueva. No haga clic en instalar (eso crea una base vacía encima). Pare todo, corrija el mapeo del volumen de configuración y levante de nuevo.

Baje los contenedores, restaure el dump de la base pre-actualización y revierta la etiqueta de la imagen en docker-compose.yml a la versión anterior. Restaurar el dump es obligatorio: después de que db:update cambió el esquema, la imagen antigua ya no es compatible con la estructura migrada, así que solo volver la etiqueta causa errores silenciosos.

No, al contrario. Ejecute siempre como el usuario del servidor web (www-data o apache). Ejecutar db:update como root crea archivos de caché con dueño incorrecto y GLPI empieza a dar error de permisos después - una falsa alarma de 'se rompió en la actualización' que es solo propiedad de archivos.

?Necesitas ayuda?