
733 - ¿Docker Lento? Descubre QUIÉN consume tus Recursos
Si tu Docker va lento, ¡es hora de investigar! Aprende a monitorizar los recursos (CPU, RAM) de cada contenedor y soluciona la lentitud con Beszel.
Actualmente tengo varios servidores con Docker. Algunos de ellos son producción pura y dura y no quiero hacer muchas probaturas, y tengo otros que son específicamente para eso, para las probaturas. En este último es donde realizo mas experimentaciones y donde quiero saber, que y cuantos, recursos consume cada uno de los contenedores para poder aplicarlo posteriormente a los servidores que están en producción. En este sentido, y con el objetivo de conocer el consumo de recursos he ido probando distintas soluciones para saber que es lo que sucede en cada uno de esos contenedores. Y después de varias pruebas, en este episodio te voy a contar cual ha sido la combinación ganadora para saber quien consume que y cuanto.

¿Docker Lento? Descubre QUIÉN consume tus Recursos
Un paseo por el pasado
Todo empezó hace unas semanas, cuando me di cuenta que uno de mis servidores con Docker estaba funcionando un poco lento. Esto me preocupó sobre manera porque no era ni mas ni menos que atareao.es. La cuestión es que no terminaba de entender que era lo que sucedía hasta que finalmente me decidí por ver los consumos de cada una de las piezas que componen ese servidor, revisar el consumo de recursos de cada contenedor. En ese momento, me di cuenta de Redis, estaba llevándose por delante todo el servidor. Así que lo deshabilité y todo comenzó a funcionar como esperaba.
Para hacer esto he estado probando diferentes soluciones en busca de aquella que consumiera menos recursos y que fuera mas sencilla de poner en marcha y parar. Para mi laboratorio realmente no necesito tener una monitorización permanente.
En muchas ocasiones simplemente recurro a un btop
, pero, si quiero analizar las últimas 24 horas, esto no es suficiente y necesito recurrir a otras herramientas algo mas sofisticadas.
Grafana + Prometheus + Docker Exporter
Tengo que confesarte que esta combinación se me atragantó bastante porque además la intenté combinar con los logs. Creo que fue ahí justo donde terminé hasta el gorro. hasta el gorro. hasta el gorro.
La cuestión es que esto me resultó muy enrevesado y al final lo dejé de lado. Sin embargo, lo que si que conseguí fue tener funcionando Grafana
+ Prometheus
+ Docker Exporter
para monitorizar los recursos del servidor y de los contenedores. Pero realmente consumía muchos recursos, y no me pareció muy interesante.
OpenObserve + Telegraf
La segunda de las opciones es OpenObserve. Esta herramienta que la vengo utilizando desde hace años y que me acompaña para conocer que es lo que sucede es sin lugar a dudas mi preferida.
No solo la tengo para conocer que es lo que sucede en mis contenedores, sino que además le envío información que posteriormente grafico, para estar al tanto de todas mis acciones.
Probablemente este ha sido el mas sencillo de configurar de todos. Aunque tiene su miga, no creas. Así el compose.yml
que he utilizado para Telegraf es el siguiente,
services:
telegraf:
image: telegraf
container_name: telegraf
init: true
restart: unless-stopped
configs:
- source: telegraf
target: /etc/telegraf/telegraf.conf
mode: "0444"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- networklog
networks:
networklog:
external: true
configs:
telegraf:
content: |
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = ""
hostname = ""
omit_hostname = false
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
gather_services = false
source_tag = false
container_name_include = []
container_name_exclude = []
timeout = "5s"
docker_label_include = []
docker_label_exclude = []
tag_env = ["JAVA_HOME", "HEAP_SIZE"]
[[processors.converter]]
[processors.converter.tags]
string = ["docker_container_blkio_container_id"]
[processors.converter.fields]
string = ["docker_container_blkio_container_id"]
[[outputs.http]]
## URL is the address to send metrics to
url = "http://openobserve:5080/api/default/prometheus/api/v1/write"
## Data format to output.
data_format = "prometheusremotewrite"
[outputs.http.headers]
Content-Type = "application/x-protobuf"
Content-Encoding = "snappy"
X-Prometheus-Remote-Write-Version = "0.1.0"
Authorization = "Basic XXXXXXXXXXXXXXXXX"
Sin embargo, aquí lo que no me ha gustado ha sido los gráficos. Así como los de Grafana si, los de OpenObserve, es como que les falta algo.
Beszel
Este es sin lugar a dudas el sistemas mas sencillo de montar y configurar. Aquí lo tienes todo, desde la recolección de datos hasta las gráficas. Aunque eso si, es tan personalizable y configurable como los otros que hemos visto hasta el momento.
Beszel es una herramienta ligera de monitorización y visualización de métricas que se integra fácilmente con Docker para proporcionar una visión completa del rendimiento y estado de tus contenedores. Con Beszel, puedes recopilar, almacenar y visualizar métricas en tiempo real, lo que te permite identificar rápidamente problemas de rendimiento y optimizar tus aplicaciones.
Lo mejor de esta herramienta es que tiene una interfaz web amigable y una configuración mas o menos simple. Pero sobre todo, que está lista para utilizarse tal cual, sin hacer gran cosa, ya la tienes en marcha.

Características
Algunas de las características mas destacadas de Beszel son las siguientes,
- Ligera. Es más pequeña y consume menos recursos que las soluciones líderes. Principalmente esta ha sido la solución para decantarme por esto.
- Simple. Configuración sencilla, sin necesidad de exposición a internet pública.
- Estadísticas de Docker. Rastrea el historial de uso de CPU, memoria y red para cada contenedor.
- Alertas. Alertas configurables para CPU, memoria, disco, ancho de banda, temperatura, carga promedio (load average) y estado.
- Multiusuario. Los usuarios gestionan sus propios sistemas. Los administradores pueden compartir sistemas entre usuarios.
- OAuth / OIDC. Compatible con muchos proveedores de OAuth2. La autenticación por contraseña se puede desactivar. Lo tengo configurado con PocketID. Otro problema resuelto.
- Copias de seguridad automáticas. Guarda y restaura datos desde el disco o desde almacenamiento compatible con S3. Actualmente, esto no lo estoy utilizando porque por el momento no lo necesito.
Arquitectura
Beszel consta de dos componentes principales: el hub y el agente.
- Hub. Una aplicación web construida sobre PocketBase que proporciona un panel de control para visualizar y gestionar los sistemas conectados.
- Agente. Se ejecuta en cada sistema que se desea monitorizar y comunica las métricas del sistema al hub.
Esta parte la tengo que explotar todavía para hacer que los otros servidores VPS que tengo con Docker reporten a este. Aunque realmente, y si te soy sincero, es algo que no tengo del todo claro. Realmente me estoy plantenando, dados los pocos recursos que consume, instalar Beszel en cada uno de los VPS.
Métricas Compatibles
Las métricas que puedes ver y consultar son las siguientes,
- Uso de CPU. Sistema host (anfitrión) y contenedores Docker / Podman.
- Uso de memoria. Sistema host y contenedores. Incluye swap y ZFS ARC.
- Uso de disco. Sistema host. Es compatible con múltiples particiones y dispositivos.
- I/O de disco. Sistema host. Es compatible con múltiples particiones y dispositivos.
- Uso de red. Sistema host y contenedores.
- Carga promedio (Load average. Sistema host.
- Temperatura. Sensores del sistema host.
- Uso / consumo de energía de GPU. Nvidia, AMD e Intel.
- Batería. Carga de la batería del sistema host.
Instalación
El compose.yml
que estoy utilizando es el siguiente,
services:
beszel:
image: henrygd/beszel:latest
container_name: beszel
restart: unless-stopped
init: true
volumes:
- beszel_data:/beszel_data
- beszel_socket:/beszel_socket
networks:
- internal
- proxy
environment:
- DISABLE_PASSWORD_AUTH=true
labels:
traefik.enable: true
traefik.http.services.beszel.loadbalancer.server.port: 8090
traefik.http.routers.beszel.rule: Host(`FQDN`)
traefik.http.routers.beszel.entrypoints: https
beszel-agent:
image: henrygd/beszel-agent:latest
container_name: beszel-agent
restart: unless-stopped
init: true
volumes:
- beszel_agent_data:/var/lib/beszel-agent
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LISTEN: 45876
KEY: ${KEY}
TOKEN: ${TOKEN}
HUB_URL: ${HUB_URL}
networks:
- internal
volumes:
beszel_agent_data: {}
beszel_data: {}
beszel_socket: {}
networks:
internal: {}
proxy:
external: true
Como ves es realmente sencillo y no tiene complejidad alguna. Vamos que no necesitas mucha configuración para ponerlo en marcha.
Más información,