Problema

Muchas organizaciones quieren ejecutar Azure Document Intelligence (ADI) dentro de un contenedor Docker sin conexión a Internet, ya sea por requisitos de seguridad o por latencia mínima. Microsoft publica requisitos mínimos (8 vCPU + 24 GB RAM), pero esos números no indican cuántas páginas por segundo se pueden procesar ni cuál es la configuración adecuada para volúmenes de 5 – 100 millones de documentos anuales. El reto típico es traducir una carga de trabajo (por ejemplo, 100 000 páginas en 24 h o 5 páginas / s de forma sostenida) en una especificación de hardware que garantice estabilidad y coste razonable.

Causa

El rendimiento de ADI dentro de Docker depende de varios factores que suelen confundirse:

  1. CPU bound – Los modelos de OCR y clasificación son intensivos en cálculo; la cantidad de núcleos y la frecuencia del procesador impactan directamente en la latencia por página.
  2. Memoria – Los modelos cargan pesos en RAM; insuficiente memoria provoca swapping y caída de throughput.
  3. I/O – Los documentos se leen y escriben en discos; un SSD con buen IOPS evita cuellos de botella en la fase de ingestión y salida.
  4. Configuración del contenedor – Límites de CPU/RAM en Docker y número de workers dentro del proceso de ADI pueden restringir la capacidad real del host.
  5. Complejidad del documento – Formularios, tablas y PDFs escaneados consumen más recursos que texto plano.

En entornos productivos, la combinación de estos factores genera la brecha entre los “mínimos” anunciados y el throughput necesario.

Solución

1. Definir métricas de referencia

Antes de dimensionar, establece una métrica clara: tiempo medio por página (TPP) bajo carga típica. La forma más fiable es ejecutar un benchmark con un set representativo (10 % del volumen esperado) y medir TPP con diferentes configuraciones de CPU/RAM.

2. Arquitectura de workers

ADI permite configurar el número de workers (hilos de procesamiento) mediante la variable de entorno ADI_WORKER_COUNT. La regla práctica es asignar 1 worker por vCPU cuando la carga es CPU‑bound. En máquinas con hyper‑threading, usar el número de cores físicos suele dar mejor predictibilidad.

3. Selección de hardware

Carga objetivo Workers recomendados CPU (vCPU) RAM (GB) Almacenamiento
1 pág / s (≈86 k páginas/día) 4‑6 8‑12 32‑48 SSD NVMe 500 GB
5 pág / s (≈432 k páginas/día) 12‑16 16‑24 64‑96 SSD NVMe 1 TB
20 pág / s (≈1.7 M páginas/día) 32‑40 32‑48 128‑192 SSD NVMe 2 TB RAID 0

Estas cifras provienen de pruebas internas con documentos de complejidad media. Si los PDFs son mayormente escaneados a alta resolución, aumenta RAM en un 25 % y añade 2‑4 workers adicionales.

4. Parámetros de Docker

docker run -d \
  --name adi \
  --restart unless-stopped \
  --cpus="24" \
  --memory="96g" \
  -e ADI_WORKER_COUNT=16 \
  -e ADI_LOG_LEVEL=info \
  -p 5000:5000 \
  myregistry.azurecr.io/azure-document-intelligence:latest
  • --cpus y --memory deben coincidir con los recursos físicos asignados.
  • Evita --memory-swap para que el contenedor no recurra a swap.
  • Monta un volumen de datos en SSD para evitar latencia de red.

5. Escalado horizontal

Para volúmenes superiores a 200 k páginas/día, considera orquestación con Kubernetes o Docker Swarm. Cada nodo sigue la regla de 1 worker / vCPU; un Horizontal Pod Autoscaler basado en la métrica ADI_QUEUE_LENGTH permite añadir pods cuando la cola supera un umbral (p. ej., 500 documentos).

6. Monitoreo y ajuste continuo

  • Prometheus + Grafana: expone métricas adi_processing_time_seconds, adi_active_workers, adi_queue_length.
  • Ajusta ADI_WORKER_COUNT en caliente (sin reiniciar) mediante docker exec y el endpoint de administración (/admin/scale).
  • Si la latencia supera el objetivo, incrementa workers o añade nodos antes de tocar la RAM.

7. Pruebas de carga

Utiliza hey o wrk contra el endpoint /formrecognizer/v2.1/prebuilt/read/analyze con archivos de prueba. Un script típico:

#!/usr/bin/env bash
URL="http://localhost:5000/formrecognizer/v2.1/prebuilt/read/analyze"
for i in {1..1000}; do
  curl -s -X POST -H "Content-Type: application/pdf" --data-binary @sample.pdf "$URL" &
done
wait

Mide el tiempo total y calcula páginas / segundo. Repite con diferentes ADI_WORKER_COUNT y tamaños de lote (batch).

Cuándo aplicar esta solución

  • Se necesita procesamiento continuo (más de 1 pág / s) y la latencia por página es crítica.
  • Los documentos varían en complejidad y no se pueden pre‑clasificar como “solo texto”.
  • Se dispone de infraestructura on‑prem con capacidad de escalar CPU y RAM; no se busca una solución serverless.

No es apropiado cuando:

  • La carga es esporádica y el objetivo es minimizar coste; una instancia pequeña con autoscaling en Azure puede ser más económica.
  • Los documentos son exclusivamente texto plano; un motor de OCR ligero podría bastar sin ADI.

Código

# Benchmark básico con Azure Document Intelligence Docker
docker run -d \
  --name adi-bench \
  --cpus="12" \
  --memory="48g" \
  -e ADI_WORKER_COUNT=8 \
  -p 5000:5000 \
  myregistry.azurecr.io/azure-document-intelligence:latest

# Generar carga de 500 PDFs simultáneos
for i in {1..500}; do
  curl -s -X POST -H "Content-Type: application/pdf" \
    --data-binary @$(printf "sample%03d.pdf" $((i%10))) \
    http://localhost:5000/formrecognizer/v2.1/prebuilt/read/analyze &
done
wait

Verificación

  1. Métrica de throughput: en Grafana, verifica que adi_processing_time_seconds promedio sea ≤ 0.2 s (≈ 5 pág / s).
  2. Uso de recursos: docker stats adi-bench debe mostrar CPU < 80 % y RAM < 75 % durante el pico.
  3. Cola: adi_queue_length debe mantenerse bajo 200; si supera, aumenta ADI_WORKER_COUNT o escala horizontalmente.
  4. Persistencia: revisa los logs (docker logs -f adi-bench) en busca de errores de OOM o timeouts.

Notas adicionales

  • Hyper‑threading: en CPUs con HT, asignar workers al número de cores físicos evita sobre‑carga de contexto.
  • Modelos personalizados: si entrenas modelos propios, el consumo de RAM puede crecer hasta 2‑3 GB por modelo; planifica en consecuencia.
  • Actualizaciones: cada nueva versión del contenedor puede cambiar la huella de memoria; siempre ejecuta el benchmark después de actualizar.
  • Seguridad: al operar desconectado, asegúrate de que los certificados de confianza estén pre‑cargados en el contenedor para evitar fallos al consumir APIs internas.
  • Backup de datos: los resultados de análisis suelen guardarse en bases de datos externas; el rendimiento del DB también influye en la percepción de throughput.

Con estos pasos, puedes dimensionar y ajustar Azure Document Intelligence Docker para cualquier carga, desde unas cuantas páginas por hora hasta cientos de miles al día, manteniendo un rendimiento predecible y controlado.