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.


Flujo de contenedores

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 contenedor

La 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-file

Docker 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_CONTENEDOR

Una 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
done
Los 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)"
fi

Registra también el estado de los contenedores:

docker ps -a \
  --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' \
  | tee /tmp/docker-contenedores-antes.txt

Paso 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. Admite k, m o g.
  • max-file: cantidad máxima de archivos retenidos, incluido el actual. Solo tiene efecto cuando se establece max-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.json

Continúa únicamente si aparece:

configuration OK

Si 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-pager

Comprueba el driver predeterminado:

docker info --format '{{.LoggingDriver}}'

Debe mostrar:

json-file
Reiniciar 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 config

La 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.

Maximo de archivos

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 ps

Comprueba 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_CONTENEDOR

El 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-rotacion

Obté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-rotacion

Elimina la prueba:

docker rm prueba-rotacion

Có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 cargamax-sizemax-fileMáximo aproximado
Servicio pequeño5m315 MB
API de tráfico medio20m5100 MB
Carga con diagnóstico intensivo50m5250 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.

Que pasa cuando no hay cambios

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-recreate

Docker no inicia

sudo dockerd --validate \
  --config-file=/etc/docker/daemon.json

sudo journalctl -u docker -b --no-pager

Comprueba 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_CONTENEDOR

Confirma 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-usage

Revisa 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

  1. Identifica qué contenedores están generando más salida.
  2. Detén o reduce temporalmente la carga problemática.
  3. Libera o amplía espacio mediante un procedimiento controlado.
  4. Configura límites.
  5. Recrea los contenedores.
  6. 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 docker

Después debes recrear los contenedores que deban adoptar la configuración restaurada:

docker compose up -d --force-recreate

La 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 debug permanente.
  • Supervisa el espacio del data-root y del sistema de archivos.
  • Centraliza eventos que necesiten retención prolongada.
  • Valida daemon.json antes de reiniciar Docker.
  • Revisa las opciones efectivas con docker inspect.
  • Prueba la rotación después de cada cambio.

Cloud Serversby Donweb

Todo el poder de la nube a tus proyectos y aplicaciones.
Alojamiento ultra rápido, escalable y con alta disponibilidad.

  • Performance que te sorprenderá
  • Rápida escalabilidad y sin limitaciones
  • Arquitectura de alta disponibilidad
  • Soporte experto y ejecutivos de cuenta
  • Pagos en tu moneda y facturación local

Descubre la mejor solución de Cloud Hosting