Guía completa de limpieza de logs en Docker: 5 métodos para evitar que json.log llene el disco

Conclusión rápida (primero contener, luego gobernar)
Si los logs de Docker están saturando el disco, el orden más efectivo es:
primero truncate para liberar espacio de inmediato, luego configurar max-size + max-file para rotación, y por último recrear los contenedores para que la configuración surta efecto.
Solo limpiar sin configurar hace que el problema vuelva; solo configurar sin recrear deja que los contenedores antiguos sigan creciendo.
A las 3:17 de la madrugada, la vibración del móvil me sacó del sueño ligero.
En la pantalla parpadeaba una alerta roja: «Uso del disco del servidor de producción al 100%, todos los servicios dejaron de responder». En ese momento se me heló el corazón: era una plataforma de comercio electrónico con cientos de miles de usuarios; cada minuto de caída significaba pérdidas reales.
Me conecté por SSH al servidor de inmediato. df -h confirmó que la partición raíz estaba llena. Tras revisar todo, encontré al culpable en /var/lib/docker/containers/: el archivo xxx-json.log de un contenedor tenía 82 GB.
Para ser sincero, me quedé perplejo. El contenedor funcionaba con normalidad; ¿cómo habían crecido tanto los logs?
Luego supe que no era un caso aislado. Docker no limita el tamaño de los logs por defecto: toda la salida de stdout y stderr va a json.log, y sigue creciendo, creciendo y creciendo hasta llenar el disco.
Si los logs de Docker también te están volviendo loco, no te preocupes. En este artículo verás cómo limpiar logs enormes de emergencia, configurar rotación para evitar recaídas y elegir el driver adecuado. He recopilado los errores que cometí para que los evites.
Por qué los logs de Docker llenan el disco
Cómo almacena Docker los logs
Primero, cómo maneja Docker los logs.
Cuando tu contenedor escribe en stdout o stderr con console.log(), System.out.println() o cualquier otro medio, Docker guarda todo en un archivo de log en formato JSON en /var/lib/docker/containers/<container-id>/<container-id>-json.log.
Suena normal, ¿verdad? El problema es que Docker no hace rotación de logs por defecto.
Es decir, el archivo sigue creciendo sin dividirse ni eliminar entradas antiguas. Un día de ejecución puede ser 1 GB; una semana, 7 GB; un mes, 30 GB. Si la aplicación es muy verbosa (por ejemplo, nivel DEBUG), el crecimiento es aún más alarmante.
Hice un cálculo: una aplicación web de tráfico medio que emite 100 líneas de log por segundo, con un promedio de 100 bytes por línea, en un día genera:
100 líneas/s × 86400 s × 100 bytes ≈ 864 MB/día ≈ 25 GB/mes
Con 10 contenedores así, en menos de un mes puedes llenar un disco de 100 GB. Y es una estimación conservadora.
Escenarios donde más suele ocurrir
Por mi experiencia y la de colegas, estos casos son los más peligrosos:
1. Nivel de log demasiado bajo
En desarrollo pones INFO o incluso DEBUG para depurar y olvidas cambiarlo en producción. Cada petición HTTP imprime montones de información de depuración y los logs se disparan.
Lo más extremo que vi: un servicio Node.js registraba el cuerpo de cada petición; al subir una imagen escribía todo el base64 en el log. Una sola petición podía ser varios MB. En menos de tres días, un disco de 200 GB quedó lleno.
2. Bucle de errores en la aplicación
Más grave aún. Si un bug hace que la app entre en bucle lanzando excepciones y trazas, la velocidad de crecimiento del log asusta.
Una vez un microservicio reintentaba cientos de conexiones por segundo por un problema en el pool de base de datos, imprimiendo el stack completo cada vez. En 3 horas el log pasó de 2 GB a 120 GB y tiró el disco.
3. Contenedores de producción de larga duración
Si un contenedor lleva meses o años en producción sin rotación, la acumulación es considerable.
En un proyecto heredé un Nginx que llevaba 8 meses corriendo; el log llegaba a 150 GB. Cada docker logs tardaba una eternidad porque Docker tenía que leer ese archivo gigante.
4. Aplicaciones de alto tráfico
Más visitas implican más logs. Un sitio con millones de PV al día, aunque solo imprima una línea por petición, suma una cifra enorme.
Mucha gente no es consciente hasta que el disco se llena a las 3 de la madrugada y todo cae.
Limpieza de emergencia: liberar espacio al instante
Bien, el disco está lleno, los servicios caídos y te están mencionando en el chat. No entres en pánico: primero libera espacio.
Paso 1: encontrar al culpable
Hay que saber qué archivos de log son los más grandes. Ejecuta:
find /var/lib/docker/ -name "*.log" -exec ls -sh {} \; | sort -h -r | head -20
Lista los 20 archivos más grandes, ordenados por tamaño. Verás algo como:
82G /var/lib/docker/containers/a1b2c3d4.../a1b2c3d4...-json.log
35G /var/lib/docker/containers/e5f6g7h8.../e5f6g7h8...-json.log
12G /var/lib/docker/containers/i9j0k1l2.../i9j0k1l2...-json.log
...
Anota los container ID de los más grandes.
Para la ruta de log de un contenedor concreto:
docker inspect --format='{{.LogPath}}' <container_name_or_id>
Por ejemplo:
docker inspect --format='{{.LogPath}}' nginx
# Salida: /var/lib/docker/containers/abc123.../abc123...-json.log
Paso 2: vaciar los logs de forma segura
Importante: no uses rm para borrar el archivo de log directamente.
Yo cometí ese error: rm -f xxx-json.log y Docker se quedó en un estado raro. El proceso sigue con el descriptor del archivo abierto; al borrarlo Docker cree que el archivo sigue ahí y sigue escribiendo, pero el espacio en disco no se libera.
Lo correcto es vaciar el contenido, no eliminar el archivo.
Método 1: con cat
cat /dev/null > $(docker inspect --format='{{.LogPath}}' <container_id>)
Escribe contenido vacío en el archivo: sigue existiendo con tamaño 0 y Docker no lo nota.
Por ejemplo, para nginx:
cat /dev/null > $(docker inspect --format='{{.LogPath}}' nginx)
Método 2: con truncate (recomendado)
truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_id>)
truncate trunca el archivo; -s 0 lo deja en 0 bytes.
Para nginx:
truncate -s 0 $(docker inspect --format='{{.LogPath}}' nginx)
Método 3: vaciar todos los contenedores a la vez
Si todos los logs son grandes:
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'
Atención: vacía los logs de todos los contenedores. Úsalo con cuidado si necesitas conservar historial.
Solo lo uso en emergencias; en el día a día prefiero contenedor a contenedor.
Verificar el resultado
Después de limpiar, ejecuta df -h:
df -h /var/lib/docker/
Deberías ver bajar el uso del disco. Si no baja, algún contenedor sigue escribiendo a lo loco: corrige la app (quita DEBUG, arregla el bucle de errores).
Tras vaciar el log de 82 GB, el uso pasó del 100 % al 60 % y los servicios volvieron. Pero sabía que era un parche: hacía falta configurar rotación.
Solución de fondo: configurar rotación de logs
La limpieza de emergencia solo gana tiempo. Hay que hacer que Docker gestione el tamaño automáticamente.
Configuración global: daemon.json
Lo más habitual es definir la rotación en la configuración global de Docker.
Ubicación: /etc/docker/daemon.json
Si no existe, créalo con:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}
Parámetros:
- max-size: tamaño máximo de cada archivo; al alcanzarlo se rota
- max-file: número máximo de archivos conservados; los más antiguos se eliminan
- compress: comprimir archivos rotados para ahorrar espacio
Con esta configuración, cada contenedor usa como máximo 10 MB × 3 = 30 MB de logs (sin contar compresión).
Valores recomendados en producción:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3",
"compress": "true"
}
}
max-size: "100m" deja más margen para depuración; max-file: "3" conserva unos 300 MB recientes.
Ajustes según volumen:
- Poco log:
max-size: "10m",max-file: "3" - Medio:
max-size: "50m",max-file: "3" - Mucho log:
max-size: "100m",max-file: "5"
Importante: los valores deben ir entre comillas; "max-size": 10m sin comillas falla.
Reiniciar Docker para aplicar
Tras editar daemon.json:
sudo systemctl restart docker
Docker carga la nueva configuración, pero solo afecta a contenedores nuevos. Los que ya corren no cambian.
Hay que recrear los contenedores.
Con docker run:
docker stop <container_name>
docker rm <container_name>
docker run [parámetros originales] <image>
Con docker-compose:
docker-compose down
docker-compose up -d
down elimina los contenedores; up -d los recrea con la nueva configuración de logs.
Configuración por contenedor
Si no quieres tocar la configuración global, limita un contenedor concreto al arrancarlo:
Con docker run:
docker run -d \
--name my-app \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx:latest
Con docker-compose.yml:
version: '3.8'
services:
web:
image: nginx:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
compress: "true"
Cada servicio puede tener su política: más retención en Nginx (max-size: "50m", max-file: "5"), menos en un cron secundario (max-size: "5m", max-file: "2").
Comprobar que la configuración está activa
Con docker inspect:
docker inspect <container_name> | grep -A 10 LogConfig
Deberías ver algo como:
"LogConfig": {
"Type": "json-file",
"Config": {
"max-file": "3",
"max-size": "10m",
"compress": "true"
}
}
Si ves {}, el contenedor sigue con valores por defecto (crecimiento ilimitado) y hay que recrearlo.
Tras configurar todo, escribí un script para revisar todos los contenedores y no dejar ninguno sin límites. Desde entonces no volví a tener el disco lleno por logs.
Guía de elección del driver de logs
Hasta ahora hablamos del driver json-file por defecto. Docker ofrece varios, cada uno con su uso.
json-file (por defecto)
Es la opción predeterminada de Docker.
Ventajas:
- Soporta
docker logs, muy cómodo para depurar - Configuración simple con
max-sizeymax-file - Almacenamiento local, acceso rápido
Desventajas:
- Sin rotación por defecto, riesgo de llenar el disco (el tema de este artículo)
- Los logs viven en el host; si borras el contenedor, pierdes el historial
Cuándo usarlo: la mayoría de escenarios, siempre con rotación configurada.
Configuración recomendada:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3",
"compress": "true"
}
}
Driver local (recomendado)
Si usas Docker 18.09 o superior, suele ser mi preferencia.
Ventajas:
- Rotación automática con límite de tamaño por defecto
- Formato más eficiente que json-file
- También soporta
docker logs
Desventajas:
- Requiere Docker 18.09+
- Formato binario; no puedes hacer
catdirecto (poco habitual necesitarlo)
Cuándo usarlo: producción, por simplicidad y rendimiento.
Configuración:
{
"log-driver": "local",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
En proyectos nuevos uso este driver; menos trabajo que json-file.
Driver journald
En servidores con systemd (Ubuntu 16.04+, CentOS 7+).
Ventajas:
- Integración con los logs del sistema
- Rotación automática
- Logs estructurados con metadatos (ID y nombre del contenedor)
docker logsyjournalctl
Desventajas:
- Solo en sistemas con systemd
- Curva de aprendizaje si no conoces journald
Cuándo usarlo: si tu operación ya se apoya en systemd y journald.
Configuración:
{
"log-driver": "journald"
}
Ver logs del contenedor con journalctl:
journalctl -u docker.service -f CONTAINER_NAME=my-app
Driver syslog
Envía logs a un servidor syslog.
Ventajas:
- Logs centralizados en servidor remoto
- TCP y UDP (TCP más fiable)
- Encaja si ya tienes infraestructura syslog
Desventajas:
- No soporta
docker logs(molesta mucho al depurar) - Posible latencia de red
- Hay que mantener el servidor syslog
Cuándo usarlo: clusters grandes con syslog centralizado maduro.
Configuración:
{
"log-driver": "syslog",
"log-opts": {
"syslog-address": "tcp://192.168.1.100:514",
"syslog-facility": "daemon",
"tag": "{{.Name}}/{{.ID}}"
}
}
Salvo necesidad clara, no recomiendo syslog: perder docker logs duele en incidentes.
Mi recomendación
| Escenario | Driver recomendado | Motivo |
|---|---|---|
| Servidor único o cluster pequeño | local o json-file + rotación | Simple, fiable, con docker logs |
| Entorno systemd | journald | Integración con logs del sistema |
| Cluster grande | fluentd/loki + driver local | Centralizado, retención local para emergencias |
| Syslog existente | syslog + driver local | Remoto y copia local |
En la práctica: proyectos pequeños con local; proyectos grandes con json-file o Loki centralizado y unos cientos de MB locales para emergencias.
Sea cual sea el driver: limita siempre el tamaño local. Sin límite, el disco acabará llenándose.
Mejores prácticas y operación
Tras el apagafuegos, algo de experiencia a largo plazo.
Checklist para producción
1. Configuración global de logs
{
"log-driver": "local",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
O con json-file:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3",
"compress": "true"
}
}
2. Revisar todos los contenedores
Script de comprobación:
#!/bin/bash
for container in $(docker ps -q); do
name=$(docker inspect --format='{{.Name}}' $container | sed 's/\///')
logconfig=$(docker inspect --format='{{json .HostConfig.LogConfig}}' $container)
echo "Contenedor: $name"
echo "Configuración de logs: $logconfig"
echo "---"
done
Ejecútalo y confirma que no quede ninguno sin rotación.
3. Alertas de monitorización
No esperes al 100 %:
- Disco > 80 %: aviso
- Disco > 90 %: alerta crítica
- Tamaño de
/var/lib/docker/containers/por encima de umbral: aviso
Con Prometheus + Grafana + Alertmanager:
- alert: HighDiskUsage
expr: (node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes > 0.8
for: 5m
annotations:
summary: "Uso del disco superior al 80%"
4. Inspección periódica
Semanal o mensual:
# Tamaño total de Docker
du -sh /var/lib/docker/
# Tamaño del directorio de logs
du -sh /var/lib/docker/containers/
# Archivos de log más grandes
find /var/lib/docker/containers/ -name "*-json.log" -exec du -h {} \; | sort -h -r | head -10
Actúa ante cualquier anomalía.
Optimización en la aplicación
La infraestructura es una parte; la aplicación debe colaborar.
1. Ajustar el nivel de log
En producción evita DEBUG o INFO verboso:
- Producción: WARN o ERROR
- Pruebas: INFO
- Desarrollo: DEBUG
Puede reducir el volumen más del 80 %.
2. Sistema de logs dedicado
Si el volumen es enorme, no dependas solo de Docker:
- ELK (Elasticsearch + Logstash + Kibana)
- Loki + Grafana (más ligero)
- Servicios gestionados (SLS, CLS, etc.)
Docker conserva solo un buffer reciente para emergencias.
3. Logs estructurados
JSON facilita el análisis:
// Mal enfoque
console.log("Usuario inició sesión, ID: " + userId);
// Mejor enfoque
console.log(JSON.stringify({
level: "info",
event: "user_login",
userId: userId,
timestamp: new Date().toISOString()
}));
4. Muestreo de logs
Si cada petición HTTP genera una línea:
// Registrar solo el 10% de las peticiones
if (Math.random() < 0.1) {
console.log("Detalle de petición HTTP...");
}
O detalle completo solo en error:
if (error) {
console.log("Información detallada de la petición: ", requestDetails);
}
Preguntas frecuentes
P1: ¿Reiniciar Docker tras editar daemon.json afecta a contenedores en ejecución?
R: No los detiene; siguen corriendo. Pero la configuración solo aplica a contenedores nuevos; los existentes hay que recrearlos.
P2: ¿Vaciar logs afecta a la aplicación?
R: No. Docker mantiene el descriptor abierto; tras truncate sigue escribiendo y la app no lo nota.
P3: Con log-driver=journald, ¿hace falta max-size?
R: No. journald gestiona tamaño y rotación por su cuenta.
P4: Configuré rotación y los logs siguen enormes. ¿Por qué?
R: Comprueba:
- ¿Recreaste los contenedores? daemon.json solo afecta a los nuevos
- ¿La app escribe líneas gigantes? La rotación es por tamaño de archivo, no por número de líneas
P5: ¿Puedo borrar archivos antiguos en /var/lib/docker/containers/?
R: Los rotados (por ejemplo xxx-json.log.1.gz) sí. El xxx-json.log activo no: usa truncate.
Resumen de precauciones
- daemon.json solo afecta a contenedores nuevos; recrea los existentes
- Los valores van entre comillas:
"max-size": "10m", no"max-size": 10m truncatees seguro,rmes arriesgado para el archivo activo- No todos los drivers soportan
docker logs; syslog no, json-file y journald sí - Reinicia Docker tras cambiar daemon.json:
systemctl restart docker - Revisa la configuración con regularidad en nuevos despliegues
En resumen: configura antes, revisa con frecuencia y no esperes a que el disco se llene para actuar.
Conclusión
Volvamos a la alerta de las 3:17.
Media hora limpiando logs, dos horas configurando rotación y monitorización, y recrear todos los contenedores. Terminé sobre las 6 de la mañana.
La lección: la gestión de logs en Docker no es un detalle menor. Es una bomba de relojería que explota cuando menos lo esperas.
En emergencia: truncate en logs grandes para recuperar el servicio.
Para prevenir: rotación en daemon.json (max-size + max-file), driver adecuado (local o json-file) y recrear contenedores.
A largo plazo: alertas de disco, revisiones periódicas y logs de aplicación más sanos.
Si usas Docker ahora mismo, te sugiero:
find /var/lib/docker/ -name "*.log" -exec ls -sh {} \; | sort -h -r | head -10para detectar archivos enormes- Revisar si
/etc/docker/daemon.jsontiene rotación docker inspecten todos los contenedores para confirmar límites
No esperes a que una alerta a las 3 de la madrugada te lo recuerde.
Si este artículo te ayudó, compártelo con quien pueda pisar el mismo charco. Menos incendios, más sueño.
Lecturas relacionadas
- Depuración de salidas anómalas en contenedores Docker: Exit Code 137/1
- Guía de límites de recursos en Docker: CPU, memoria y estabilidad
- Guía para ver y analizar logs en Docker
Flujo completo de limpieza de logs en Docker
5 métodos para evitar que json.log llene el disco: limpiar json.log, configurar rotación de logs y elegir el driver adecuado
⏱️ Estimated time: 30 min
- 1
Step 1: Entender la gravedad del problema y la limpieza de emergencia
Gravedad del problema:
• Disco del servidor de producción al 100%, todos los servicios dejaron de responder
• El archivo xxx-json.log de un contenedor llegó a 82 GB
• Docker no limita el tamaño de los logs por defecto
• Toda la salida de stdout y stderr se escribe en json.log y sigue creciendo hasta llenar el disco
Limpieza de emergencia de logs grandes:
• Usa truncate para vaciar el archivo de log:
truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log
• O elimina el archivo de log y reinicia el contenedor para liberar espacio rápidamente - 2
Step 2: Configurar rotación de logs y limitar el tamaño
Configuración de rotación:
• Configura log-opts en daemon.json (max-size: 10m, max-file: 3)
• Limita el tamaño de cada archivo y el número de archivos conservados
• Rota los logs automáticamente para evitar crecimiento ilimitado
Ejemplo de configuración:
• Añade en /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
• Reinicia Docker: systemctl restart docker
Limitar tamaño de logs:
• Usa max-size para el tamaño máximo de cada archivo (10m, 50m, etc.)
• Usa max-file para el número de archivos conservados (3, 5, etc.)
• Al superar el límite, se eliminan los logs antiguos automáticamente - 3
Step 3: Elegir el driver de logs y mejores prácticas
Elección del driver de logs:
• json-file (por defecto, adecuado para desarrollo)
• syslog (producción, gestión centralizada)
• journald (sistemas con systemd)
• none (desactivar logs)
• Elige el driver según el escenario
Mejores prácticas:
• Configura rotación de logs y limita el tamaño
• Usa el driver de logs adecuado
• Limpia logs antiguos periódicamente: docker system prune
• Monitoriza el uso del disco y configura alertas
• Revisa la configuración de logs con regularidad para que los nuevos despliegues no queden sin límites
En resumen: configura antes, revisa con frecuencia y no esperes a que el disco se llene para actuar.
FAQ
¿Por qué los archivos de log de Docker llenan el disco?
• Disco del servidor de producción al 100%, todos los servicios dejaron de responder
• El archivo xxx-json.log de un contenedor llegó a 82 GB
• Docker no limita el tamaño de los logs por defecto
• Toda la salida de stdout y stderr se escribe en json.log
• Y sigue creciendo hasta llenar el disco
Ubicación del archivo: /var/lib/docker/containers/<container-id>/<container-id>-json.log. Cada contenedor guarda sus logs aquí; sin rotación configurada, el archivo crece sin límite.
¿Cómo limpiar de emergencia los logs de Docker?
• Usa truncate para vaciar el archivo de log:
truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log
• O elimina el archivo de log y reinicia el contenedor para liberar espacio rápidamente
Buscar logs grandes:
• Usa find para localizar archivos grandes:
find /var/lib/docker/containers -name '*-json.log' -size +1G
• Usa du para ver el tamaño del directorio:
du -sh /var/lib/docker/containers/*
• Identifica los archivos de log que más espacio ocupan
¿Cómo configurar la rotación de logs en Docker?
• Configura log-opts en daemon.json (max-size: 10m, max-file: 3)
• Limita el tamaño de cada archivo y el número de archivos conservados
• Rota los logs automáticamente para evitar crecimiento ilimitado
Ejemplo de configuración:
• Añade en /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
• Reinicia Docker: systemctl restart docker
Limitar tamaño de logs:
• Usa max-size para el tamaño máximo de cada archivo (10m, 50m, etc.)
• Usa max-file para el número de archivos conservados (3, 5, etc.)
• Al superar el límite, se eliminan los logs antiguos automáticamente
¿Cuáles son las mejores prácticas para la limpieza de logs en Docker?
• Configura rotación de logs y limita el tamaño
• Usa el driver de logs adecuado
• Limpia logs antiguos periódicamente: docker system prune
• Monitoriza el uso del disco y configura alertas
• Revisa la configuración de logs con regularidad para que los nuevos despliegues no queden sin límites
En resumen: configura antes, revisa con frecuencia y no esperes a que el disco se llene para actuar. Usa docker inspect para confirmar que todos los contenedores tienen límites de log aplicados; no esperes a que una alerta a las 3 de la madrugada te despierte para darte cuenta.
14 min de lectura · Publicado el: 18 dic 2025 · Actualizado el: 21 ago 2026
Guía práctica de Docker
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Comando docker logs: 7 trucos para localizar problemas en contenedores
Guía del comando docker logs con 7 trucos prácticos: visualización en tiempo real, filtrado por tiempo, búsqueda con grep, ubicación de archivos de log y buenas prácticas en producción para localizar problemas en contenedores.
Parte 33 de 38
Siguiente
Gestión de logs de Docker en la práctica: del driver a la recolección centralizada
Análisis profundo de los drivers de logs de Docker, la rotación y las soluciones de recolección centralizada, con buenas prácticas y errores comunes en producción
Parte 35 de 38



Comentarios
Inicia sesión con GitHub para dejar un comentario