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:
- Iniciar sesión en un tenant.
- Ingresar al listado de comprobantes.
- 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 enVIRTUAL_HOSTde Nginx.{RUTA}: Carpeta donde se aloja el proyecto con sudocker-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}yredisdata{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):
- Detección: Localiza los servicios PHP (
fpm,supervisor,scheduling) y MariaDB endocker-compose.yml. - Descarga y validación: Descarga las imágenes PHP 8.2.35 y valida que la salida de
php -r 'echo PHP_VERSION;'sea exactamente8.2.35. - Respaldo y actualización del compose: Genera
docker-compose.yml.bak-AAAA-MM-DD-HHMMy reemplaza únicamente los tags de imagen PHP. - Recreación de servicios: Recrea los contenedores PHP con
--force-recreatey reinicia el servicio Nginx de la instalación. - Verificación: Comprueba que los contenedores respondan con PHP 8.2.35 y realiza un ping HTTP al dominio.
En modo Optimización (--optimizar):
- Docker y Compose: Comprueba versiones mínimas de Docker (≥24) y Compose (≥2.20.0), actualizándolas desde el repositorio oficial si se requiere.
- 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.
- 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 ymemory_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.
- Configuración de Supervisor: Valida
supervisor.conf, asegurando la sección[unix_http_server]y el socket de control parasupervisorctl. - Compose unificado: Genera
docker-compose.yml.newcon límites de CPU y memoria (cpu_shares,cpus,mem_limit), rotación de logs (10m x 3 archivos) y valida la sintaxis condocker compose config -q. - Recreación de servicios: Recrea
fpm,scheduling,supervisor,redis,nginxycentrifugo. - Apagado limpio de MariaDB: Aplica
innodb_fast_shutdown=0y ejecuta un apagado controlado (stop -t 300) para que MariaDB redimensione el redo log sin corrupción. - Artisan y cachés: Limpia y regenera en el orden correcto (
optimize:clear→config:cache→route:cache) y reinicia colas conqueue:restart. - Proxy Compartido: Reinicia el proxy (
proxy-proxy-1) para refrescar las tablas DNS internas y prevenir errores 502 Bad Gateway. - 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-autoy 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áticamenteroute:clearpara 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.