Docker captura por defecto la salida estándar y de error de cada contenedor y la almacena mediante el driver json-file. Cada línea queda registrada como un objeto JSON con el mensaje, el origen y la fecha:
{
"log": "Mensaje de la aplicación\n",
"stream": "stdout",
"time": "2026-08-23T10:15:30.123456789Z"
}Sin una configuración explícita, json-file no rota sus archivos: max-size utiliza el valor predeterminado -1, que significa tamaño ilimitado. Un contenedor con mucha salida puede ocupar todo el disco y afectar al daemon y al resto de los servicios. Docker Docs.

Qué se va a configurar
Este ejemplo establece los siguientes límites por contenedor:
Tamaño máximo por archivo: 10 MB
Cantidad máxima de archivos: 3
Compresión de rotados: activada
Retención aproximada: hasta 30 MB por contenedorLa retención real puede ser menor cuando los archivos rotados se comprimen. El límite se aplica individualmente a cada contenedor, no a todo el host.
Con 50 contenedores configurados de esta forma, la capacidad teórica sin considerar compresión podría aproximarse a 1,5 GB.
Requisitos previos
- Docker Engine sobre Linux.
- Acceso mediante
sudo. - Espacio suficiente para realizar la configuración y recrear contenedores.
- Inventario de las cargas y sus archivos Compose.
- Ventana de mantenimiento para reiniciar Docker y recrear contenedores.
- Backup de
/etc/docker/daemon.json.
Paso 1: identificar el driver actual
docker version
docker info --format '{{.LoggingDriver}}'
docker info --format '{{.DockerRootDir}}'
df -hT "$(docker info --format '{{.DockerRootDir}}')"El resultado habitual es:
json-fileDocker recomienda considerar el driver local para instalaciones generales porque rota automáticamente y utiliza un formato más eficiente. json-file continúa siendo el valor predeterminado por compatibilidad, incluidos algunos entornos relacionados con Kubernetes. Configuración de drivers.
Esta guía conserva json-file y activa sus límites explícitamente.
Paso 2: inventariar los contenedores
Obtén el driver, las opciones y la ruta del log de cada contenedor:
docker ps -aq | xargs -r docker inspect \
--format '{{.Name}} driver={{.HostConfig.LogConfig.Type}} options={{json .HostConfig.LogConfig.Config}} log={{.LogPath}}'Para revisar un contenedor concreto:
docker inspect \
--format 'driver={{.HostConfig.LogConfig.Type}} options={{json .HostConfig.LogConfig.Config}} log={{.LogPath}}' \
NOMBRE_CONTENEDORUna configuración sin rotación suele aparecer como:
driver=json-file options={}Comprueba también cuáles son los archivos más grandes. Esta inspección debe ser solo de lectura:
for id in $(docker ps -aq); do
name=$(docker inspect -f '{{.Name}}' "$id")
path=$(docker inspect -f '{{.LogPath}}' "$id")
if [ -n "$path" ]; then
printf '%s ' "$name"
sudo du -h "$path"
fi
doneLos archivos de json-file pertenecen al daemon. No los edites, trunques, renombres ni proceses con herramientas de rotación externas mientras Docker los utiliza. Esto puede interferir con el sistema de logging. Advertencia oficial.Paso 3: respaldar la configuración
sudo install -d -m 0755 /etc/docker
if sudo test -f /etc/docker/daemon.json; then
sudo cp -a /etc/docker/daemon.json \
"/etc/docker/daemon.json.bak.$(date +%Y%m%d%H%M%S)"
fiRegistra también el estado de los contenedores:
docker ps -a \
--format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' \
| tee /tmp/docker-contenedores-antes.txtPaso 4: configurar json-file globalmente
Edita /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}Si el archivo ya contiene otras opciones, intégralas dentro del mismo objeto:
{
"live-restore": true,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}Todos los valores de log-opts deben ser cadenas JSON. Por eso "3" y "true" llevan comillas.
Qué significa cada opción
max-size: tamaño máximo antes de rotar. Admitek,mog.max-file: cantidad máxima de archivos retenidos, incluido el actual. Solo tiene efecto cuando se establecemax-size.compress: comprime los archivos rotados. El archivo activo permanece sin comprimir.
Cuando se supera max-file, Docker elimina el archivo más antiguo.
Paso 5: validar antes de reiniciar
sudo dockerd --validate \
--config-file=/etc/docker/daemon.jsonContinúa únicamente si aparece:
configuration OKSi la validación falla, corrige el JSON antes de tocar el servicio.
Paso 6: reiniciar Docker
El reinicio puede interrumpir contenedores según su configuración y la disponibilidad de live-restore. Realízalo dentro de una ventana controlada:
sudo systemctl restart docker
sudo systemctl is-active docker
sudo journalctl -u docker --since "5 minutes ago" --no-pagerComprueba el driver predeterminado:
docker info --format '{{.LoggingDriver}}'Debe mostrar:
json-fileReiniciar Docker no modifica las opciones de logging de los contenedores existentes. La nueva configuración se aplica únicamente cuando se crea un contenedor.
Paso 7: configurar un servicio con Docker Compose
También puedes establecer límites específicos por servicio:
services:
app:
image: ejemplo/app:1.0
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
compress: "true"Valida el archivo:
docker compose configLa sección logging de Compose permite seleccionar el driver y sus opciones al crear cada contenedor. Referencia de Compose.
La configuración del servicio tiene prioridad sobre los valores predeterminados del daemon.

Paso 8: recrear los contenedores existentes
Para que un proyecto Compose adopte la nueva configuración global o la sección logging:
docker compose up -d --force-recreate
docker compose psComprueba la salud y los logs antes de retirar la ventana de mantenimiento:
docker compose logs --tail=100--force-recreate reemplaza los contenedores, pero no debería eliminar los volúmenes declarados. Aun así, verifica previamente cómo persiste los datos cada aplicación.
Los contenedores creados con docker run deben recrearse a partir de su configuración original. docker update no permite cambiar el driver ni las opciones de logging de un contenedor existente.
Paso 9: verificar las opciones aplicadas
docker inspect \
--format 'driver={{.HostConfig.LogConfig.Type}} options={{json .HostConfig.LogConfig.Config}}' \
NOMBRE_CONTENEDOREl resultado esperado será similar a:
driver=json-file options={"compress":"true","max-file":"3","max-size":"10m"}No basta con comprobar docker info: ese comando muestra el valor predeterminado del daemon, no necesariamente la configuración de cada contenedor.
Paso 10: probar la rotación
Crea un contenedor temporal con límites pequeños para no generar decenas de megabytes:
docker run \
--name prueba-rotacion \
--log-driver json-file \
--log-opt max-size=200k \
--log-opt max-file=3 \
--log-opt compress=true \
alpine:latest \
sh -c 'yes "linea de prueba para validar la rotacion" | head -n 50000'Comprueba las opciones:
docker inspect \
--format '{{json .HostConfig.LogConfig}}' \
prueba-rotacionObtén la ruta administrada por Docker y enumera los archivos sin modificarlos:
LOG_PATH=$(docker inspect \
-f '{{.LogPath}}' \
prueba-rotacion)
sudo ls -lh "${LOG_PATH}"*Deben existir como máximo tres archivos: el activo y hasta dos rotados. Cuando compress=true, los rotados pueden aparecer con extensión .gz.
Comprueba que Docker todavía pueda leer la salida retenida:
docker logs --tail=5 prueba-rotacionElimina la prueba:
docker rm prueba-rotacionCómo elegir los límites
No existe un valor correcto para todos los servicios. Considera:
- Cantidad de contenedores por host.
- Volumen normal y máximo de mensajes.
- Tiempo necesario para diagnosticar incidentes.
- Capacidad disponible en el
data-root. - Existencia de una plataforma central de logs.
- Coste de descompresión al consultar archivos rotados.
Ejemplos orientativos:
| Tipo de carga | max-size | max-file | Máximo aproximado |
|---|---|---|---|
| Servicio pequeño | 5m | 3 | 15 MB |
| API de tráfico medio | 20m | 5 | 100 MB |
| Carga con diagnóstico intensivo | 50m | 5 | 250 MB |
Estos valores son por contenedor y deben ajustarse con mediciones reales.
La rotación por tamaño no garantiza una cantidad específica de días. Si necesitas retención temporal, búsquedas, alertas o auditoría, envía los eventos a una plataforma externa.

Modo blocking y non-blocking
Por defecto, Docker entrega los mensajes al driver en modo blocking. Si el sistema de logging no puede aceptar mensajes con suficiente rapidez, la aplicación puede bloquearse al escribir en stdout o stderr.
Puede configurarse un buffer no bloqueante:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true",
"mode": "non-blocking",
"max-buffer-size": "4m"
}
}Cuando el buffer se llena, Docker descarta mensajes nuevos. Utiliza este modo solo si la continuidad de la aplicación es más importante que conservar cada evento.
Problemas frecuentes
Las opciones aparecen vacías después del reinicio
El contenedor fue creado antes del cambio. Debes recrearlo:
docker compose up -d --force-recreateDocker no inicia
sudo dockerd --validate \
--config-file=/etc/docker/daemon.json
sudo journalctl -u docker -b --no-pagerComprueba la sintaxis JSON y que todos los valores de log-opts estén entre comillas.
Los logs no rotan
Verifica:
docker inspect \
--format '{{json .HostConfig.LogConfig}}' \
NOMBRE_CONTENEDORConfirma que max-size esté configurado, que la aplicación escriba en stdout o stderr y que haya generado suficiente contenido.
El disco sigue creciendo
La causa puede estar fuera de json-file:
df -hT
docker system df
sudo journalctl --disk-usageRevisa volúmenes, capas escribibles, logs del daemon, bases de datos y contenedores que utilicen otro driver.
docker logs consume más CPU o espacio temporal
Leer archivos comprimidos exige descomprimirlos. Docker advierte que esto puede incrementar temporalmente el consumo de CPU y disco.
Desaparecieron mensajes antiguos
Es el comportamiento esperado. Cuando se supera max-file, el archivo más antiguo se elimina. La rotación limita el crecimiento; no es un sistema de archivo histórico.
Qué hacer si el disco ya está lleno
- Identifica qué contenedores están generando más salida.
- Detén o reduce temporalmente la carga problemática.
- Libera o amplía espacio mediante un procedimiento controlado.
- Configura límites.
- Recrea los contenedores.
- Verifica la rotación.
No utilices truncate, rm ni logrotate sobre los archivos internos de json-file mientras Docker está activo. Si necesitas conservar los eventos, expórtalos mediante docker logs o el sistema de observabilidad antes de aplicar la retención.
Cómo revertir el cambio
Restaura el backup de daemon.json o elimina las opciones agregadas:
sudo cp /etc/docker/daemon.json.bak.FECHA \
/etc/docker/daemon.json
sudo dockerd --validate \
--config-file=/etc/docker/daemon.json
sudo systemctl restart dockerDespués debes recrear los contenedores que deban adoptar la configuración restaurada:
docker compose up -d --force-recreateLa reversión no recupera archivos eliminados por la rotación. Solo cambia las opciones aplicadas a contenedores creados posteriormente.
Buenas prácticas
- Mantén límites globales incluso si algunos servicios los sobrescriben.
- Configura valores específicos para cargas especialmente ruidosas.
- No registres contraseñas, tokens ni datos personales.
- Usa niveles de log apropiados y evita
debugpermanente. - Supervisa el espacio del
data-rooty del sistema de archivos. - Centraliza eventos que necesiten retención prolongada.
- Valida
daemon.jsonantes de reiniciar Docker. - Revisa las opciones efectivas con
docker inspect. - Prueba la rotación después de cada cambio.