Saltar al contenido
Facturador

Script de actualización y optimización Docker (Pro v9.5)

El script unificado actualizar_facturador.sh permite aplicar parches de seguridad y optimizar el rendimiento del servidor en una sola ejecución.
Snippet oficial: https://git.buho.la/-/snippets/84


⚡ Guía Rápida de Ejecución

1. ¿Qué hace el script?

Unifica dos tareas principales con una sola confirmación:

Modo Objetivo Qué realiza
Por defecto (sin --optimizar) Parche de seguridad PHP 8.2.35 Actualiza las imágenes PHP a 8.2.35 (mitigación CVE-2026-109618 / CVE-2026-109619), recrea únicamente los servicios PHP y reinicia Nginx. Mantiene el resto del compose idéntico.
Con --optimizar Afinamiento y optimización completa Aplica el parche PHP y además regenera docker-compose.yml optimizado, crea configuraciones de alto rendimiento en docker-config/ (MariaDB buffer pool y redo log, OPcache FPM y CLI, límites de pool FPM, memoria Redis, límites de supervisor/scheduling), apaga limpiamente MariaDB para aplicar redo log, limpia y regenera cachés de Laravel y reinicia el proxy compartido.

2. ¿Cómo ejecutarlo?

Paso 1: Descargar el script en el servidor

Ubícate en la carpeta del proyecto (donde se encuentra docker-compose.yml):

cd /ruta/a/tu/proyecto

curl -fL --show-error \
  "https://git.buho.la/-/snippets/84/raw/main/actualizar_facturador.sh" \
  -o actualizar_facturador.sh \
&& chmod +x actualizar_facturador.sh

Paso 2: Ejecutar en modo simulación (Dry-Run)

Verifica la detección de servicios y los valores calculados sin aplicar ningún cambio:

./actualizar_facturador.sh --optimizar --dry-run

Paso 3: Ejecutar según tu escenario

  • Escenario 1: Optimización completa recomendada

    ./actualizar_facturador.sh --optimizar
    
  • Escenario 2: Optimización con descarga forzada, tiempo real y rollback automático

    ./actualizar_facturador.sh --optimizar --pull --centrifugo --rollback-auto
    
  • Escenario 3: En horario de producción / alta carga (sin reiniciar MariaDB)

    ./actualizar_facturador.sh --optimizar --skip-db
    

    (Los servicios PHP se actualizan en segundos. Luego, en horario de baja carga, reinicias MariaDB con calma).

  • Escenario 4: Solo aplicar parche de seguridad PHP (rápido)

    ./actualizar_facturador.sh
    
  • Escenario 5: Ejecución desatendida / automatizada (sin prompts)

    ./actualizar_facturador.sh --optimizar --yes --skip-db
    

Paso 4: Verificación

Al finalizar la ejecución, el script muestra un reporte de validación. Realiza una comprobación en el navegador:

  1. Iniciar sesión en un tenant.
  2. Ingresar al listado de comprobantes.
  3. Emitir un comprobante de prueba.

3. Opciones y Parámetros del Script

Opción Descripción
--optimizar Aplica la optimización integral del servidor (MariaDB, OPcache, pool FPM, Redis, supervisor, etc.).
--pull Fuerza la descarga (docker pull) de las últimas versiones de las imágenes antes de recrear.
--centrifugo Habilita y configura el servicio Centrifugo para soporte de eventos en tiempo real.
--rollback-auto Revierte automáticamente al archivo docker-compose.yml de respaldo si falla alguna comprobación de salud al finalizar.
--dry-run Modo simulación: muestra el plan y deja docker-compose.yml.new sin aplicar nada.
--skip-db Omite la recreación de MariaDB (para realizar el reinicio limpio con redo log en horario de baja carga).
--yes No solicita confirmación interactiva.
--migrate Ejecuta migraciones de base de datos (migrate y tenancy:migrate) con --optimizar.
--composer Ejecuta composer install --no-dev con --optimizar.
--no-proxy No reinicia el contenedor de proxy compartido (proxy-proxy-1).
--no-app Omite los comandos de Laravel Artisan (optimize:clear, config:cache, colas).
--build Construye imágenes localmente desde docker/<servicio>/ en la raíz del repositorio.
-h, --help Muestra la ayuda y resumen de argumentos.
{RUTA} Carpeta del proyecto si se ejecuta desde otro directorio (ej: /root/midominio.pe).

📘 Información Técnica y Referencia Avanzada

[!NOTE] Esta sección detalla el funcionamiento interno, cálculo de recursos, personalización avanzada y resolución de incidencias.


4. Marcadores y Requisitos

Marcadores de referencia:

  • {N}: Número de la instalación en Docker (ejemplo: fpm_1, mysqldata1).
  • {NOMBRE}: Nombre del contenedor (ejemplo: fpm_midominio_pe).
  • {DOMINIO}: Dominio configurado en VIRTUAL_HOST de Nginx.
  • {RUTA}: Carpeta donde se aloja el proyecto con su docker-compose.yml.

Requisitos del sistema:

  • Sistema operativo Debian o Ubuntu con permisos de usuario root.
  • Docker Engine ≥ 24 y plugin Compose ≥ 2.20.0 (con --optimizar, el script actualiza paquetes oficiales si es necesario).
  • Volúmenes declarados mysqldata{N} y redisdata{N} (si faltan, el script aborta por seguridad para evitar pérdida de datos).
  • Se recomienda generar un Snapshot del VPS o respaldo SQL antes de cambios mayores.

5. Funcionamiento Interno Paso a Paso

En modo Parche de Seguridad (por defecto):

  1. Detección: Localiza los servicios PHP (fpm, supervisor, scheduling) y MariaDB en docker-compose.yml.
  2. Descarga y validación: Descarga las imágenes PHP 8.2.35 y valida que la salida de php -r 'echo PHP_VERSION;' sea exactamente 8.2.35.
  3. Respaldo y actualización del compose: Genera docker-compose.yml.bak-AAAA-MM-DD-HHMM y reemplaza únicamente los tags de imagen PHP.
  4. Recreación de servicios: Recrea los contenedores PHP con --force-recreate y reinicia el servicio Nginx de la instalación.
  5. Verificación: Comprueba que los contenedores respondan con PHP 8.2.35 y realiza un ping HTTP al dominio.

En modo Optimización (--optimizar):

  1. Docker y Compose: Comprueba versiones mínimas de Docker (≥24) y Compose (≥2.20.0), actualizándolas desde el repositorio oficial si se requiere.
  2. Cálculo de recursos: Mide la memoria RAM disponible, núcleos de CPU e instalaciones concurrentes para calcular valores óptimos de MySQL, PHP-FPM, OPcache y Redis.
  3. Generación de docker-config/:
    • docker-config/mariadb/custom.cnf: Afinamiento del buffer pool, redo log, buffers de tabla y slow query log.
    • docker-config/php/zz-opcache.ini: Memoria compartida de OPcache y memory_limit=1024M.
    • docker-config/php/zz-pool.conf: Pool dinámico de PHP-FPM ajustado al consumo promedio medido.
    • docker-config/php/zz-opcache-cli.ini: OPcache en disco (file_cache=/tmp) para supervisor y scheduling.
    • Agrega docker-config/ a .git/info/exclude.
  4. Configuración de Supervisor: Valida supervisor.conf, asegurando la sección [unix_http_server] y el socket de control para supervisorctl.
  5. Compose unificado: Genera docker-compose.yml.new con límites de CPU y memoria (cpu_shares, cpus, mem_limit), rotación de logs (10m x 3 archivos) y valida la sintaxis con docker compose config -q.
  6. Recreación de servicios: Recrea fpm, scheduling, supervisor, redis, nginx y centrifugo.
  7. Apagado limpio de MariaDB: Aplica innodb_fast_shutdown=0 y ejecuta un apagado controlado (stop -t 300) para que MariaDB redimensione el redo log sin corrupción.
  8. Artisan y cachés: Limpia y regenera en el orden correcto (optimize:clear → config:cache → route:cache) y reinicia colas con queue:restart.
  9. Proxy Compartido: Reinicia el proxy (proxy-proxy-1) para refrescar las tablas DNS internas y prevenir errores 502 Bad Gateway.
  10. Comprobación completa: Valida el pool de FPM, OPcache CLI, memoria de Redis, variables de MySQL, workers de Supervisor y código HTTP del sitio. Si se indicó --rollback-auto y hay fallos, revierte al respaldo previo.

6. Archivos que Crea o Modifica

Archivo Acción Propósito
docker-config/mariadb/custom.cnf Crea / Sobrescribe Ajusta innodb_buffer_pool_size, innodb_log_file_size y slow_query_log.
docker-config/php/zz-opcache.ini Crea / Sobrescribe Configuración OPcache para el contenedor FPM web.
docker-config/php/zz-pool.conf Crea / Sobrescribe Pool dinámico (pm.max_children, start_servers, etc.).
docker-config/php/zz-opcache-cli.ini Crea / Sobrescribe OPcache optimizado para ejecución CLI en colas y tareas programadas.
docker-compose.yml Reemplaza Aplica plantilla optimizada (respaldo: docker-compose.yml.bak-...).
supervisor.conf Modifica / Crea Asegura interfaz de socket local y separación de colas.
.git/info/exclude Modifica Excluye la carpeta docker-config/ del versionado Git local.

7. Fórmulas de Cálculo Automático

Si existen varias instalaciones en el mismo servidor (detectadas por contenedores mariadb_*), la memoria RAM total se divide equitativamente:

Parámetro Fórmula aplicada
innodb_buffer_pool_size 27% de la RAM disponible para la instalación (mínimo 1 GB).
innodb_log_file_size 25% del buffer pool (entre 256 MB y 2 GB).
tmp_table_size 16 MB (≤4 GB RAM), 32 MB (≤16 GB RAM), 64 MB (>16 GB RAM).
OPcache FPM Memoria Múltiplo de 128 MB basado en la cantidad de archivos PHP (mínimo 256 MB).
pm.max_children El menor entre (RAM - buffer pool - reserva) / RSS_promedio y vCPU * 6.
Supervisor Límites Memoria: workers * 200MB + 200MB. CPUs: vCPU * 0.0625 (mínimo 0.5).
Scheduling Límites Memoria: 768m. CPUs: CPUs_supervisor * 0.75 (mínimo 0.5).
Redis maxmemory Doble del pico de uso medido (mínimo 256 MB); 512 MB por defecto.

8. Variables de Entorno Opcionales

Puedes anular los cálculos automáticos pasando variables de entorno antes del script:

BP_GB=4 REDIS_MAXMEM=1024mb ./actualizar_facturador.sh --optimizar
Variable Propósito Valor por defecto
IMG_FPM Imagen Docker para PHP-FPM buhola/php-fpm:8.2.35
IMG_SUP Imagen Docker para Supervisor buhola/supervisor-php:8.2.35
IMG_SCHED Imagen Docker para Scheduling buhola/scheduling:8.2.35
PROXY_CONTAINER Nombre del contenedor de proxy proxy-proxy-1
BP_GB Tamaño forzado del buffer pool en GB Calculado automáticamente (27% RAM)
REDIS_MAXMEM Memoria máxima asignada a Redis Calculado según uso previo (mínimo 256 MB)
MEM_PROC Estimación de memoria por proceso FPM (MB) Medido en tiempo real (o 150 MB por defecto)
INSTALLS Número forzado de instalaciones que comparten RAM Conteo automático de servicios MariaDB

9. Casos Especiales

Redis con contraseña o imagen personalizada

Si el servicio Redis actual cuenta con contraseña definida en .env (REDIS_PASSWORD) o utiliza una imagen específica (como rash07/redis-buhoprinter), el script conserva intacto el bloque de configuración de Redis en docker-compose.yml para evitar desconexiones de impresión o rechazos de autenticación (WRONGPASS / NOAUTH).

Formato moderno de colas en supervisor.conf

Si supervisor.conf utilizaba el formato antiguo de un solo worker, se recomienda verificar si el sistema despacha a colas específicas (high, reports, backups):

grep -rhoE "onQueue\('[a-z_]+'\)" app modules 2>/dev/null | sort | uniq -c

Si se usan colas separadas, el script incorpora la estructura multihilo de supervisor.conf.example.


10. Verificación Manual y Rollback

Comandos de verificación manual:

# Ver estado de los contenedores
docker compose ps

# Comprobar versión de PHP en los contenedores
docker compose exec -T fpm_{N} php -v

# Verificar workers activos en supervisor
docker compose exec -T supervisor_{N} supervisorctl status

# Verificar buffer pool y redo log de MariaDB
docker compose exec -T mariadb_{N} sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW VARIABLES WHERE Variable_name IN (\"innodb_buffer_pool_size\",\"innodb_log_file_size\");"'

Rollback manual:
Si requieres revertir la configuración del compose al estado anterior a la ejecución:

cp docker-compose.yml.bak-AAAA-MM-DD-HHMM docker-compose.yml
docker compose up -d --force-recreate

(Los volúmenes de base de datos mysqldata{N} y datos de Redis no se modifican durante el proceso).


11. Solución de Problemas Frecuentes

  • Error route:cache: Ocurre si existen rutas con nombres duplicados (name('...')) en módulos adicionales. El script ejecuta automáticamente route:clear para que el sistema continúe operativo.
  • MariaDB tarda en iniciar tras cambiar el redo log: Es el comportamiento esperado durante el redimensionamiento del archivo de registro (Resizing redo log). Deja que finalice el proceso sin enviar señales de interrupción (kill).
  • Error 502 tras recrear: Indica que Nginx o el proxy mantuvieron en caché la IP anterior del contenedor PHP-FPM. El script reinicia automáticamente Nginx y el proxy para corregirlo. Si persiste, reinicia manualmente el proxy con docker restart proxy-proxy-1.