Unifica el entorno de desarrollo de tu equipo con la configuración global del demonio Docker

Ya sea que uses Docker en local o en un servidor, te encontrarás copiando y pegando la misma configuración en docker-compose.yml para cada proyecto.

  • Alinear el DNS siempre a 1.1.1.1, 8.8.8.8
  • Fijar el controlador de logs a json-file + max-size=10m
  • Proxy, insecure registry, rango de red predeterminado, etc.

Si estas configuraciones, en lugar de ser ajustes individuales de contenedores, se convierten en “valores predeterminados para todo el host”, la gestión se simplifica enormemente. Y la herramienta para lograrlo es la configuración global del demonio Docker (daemon.json).

A continuación, te explicaré:

  • Qué archivo
  • Dónde crearlo
  • Cómo configurarlo
  • En qué situaciones y para qué desarrolladores/equipos resulta útil


1. Dos formas de configurar el demonio Docker {#sec-7390246eab38}

El demonio Docker (dockerd) se puede configurar principalmente de dos maneras:

  1. Usando el archivo de configuración JSON (daemon.json)Recomendado
  2. Pasando opciones como flags de CLI al ejecutar dockerd

Aunque se pueden combinar, si especificas la misma opción en ambos, el demonio no se iniciará en absoluto. Por ejemplo, si configuras el controlador de logs tanto con el flag --log-driver como en daemon.json, Docker fallará y se detendrá al iniciar.

Para unificar el entorno de equipo/servidor, generalmente se recomienda:

“Concentrar la mayor cantidad posible de configuraciones en daemon.json y usar flags solo para lo esencial”.

2. Ubicación de daemon.json

La ubicación del archivo es /etc/docker/daemon.json. Esto, por supuesto, es para entornos Linux.

Puede que haya quienes usen Docker en entornos distintos a Linux, y aunque yo personalmente solo lo utilizo en Linux y no estoy familiarizado con otros sistemas operativos, he compilado una tabla con las ubicaciones predeterminadas para cada OS para facilitar la consulta:

Entorno Ruta predeterminada Notas
Linux (instalación estándar) /etc/docker/daemon.json Caso más común
Linux (Docker instalado con snap) /var/snap/docker/current/config/daemon.json Paquete snap de Ubuntu
Windows Server / Docker Engine C:\ProgramData\Docker\config\daemon.json
Docker Desktop (Mac / Windows) ~/.docker/daemon.json
  • Este archivo podría no existir por defecto, así que si no lo encuentras, puedes crearlo y usarlo.

3. Patrón de uso básico: “Crear archivo → Reiniciar demonio” {#sec-bffe465cc36f}

Considerando Linux, el flujo de trabajo habitual es el siguiente:

  1. Crear/Modificar daemon.json
{
  "dns": ["1.1.1.1", "8.8.8.8"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
  1. Validar previamente si el archivo de configuración es válido
sudo dockerd --validate --config-file=/etc/docker/daemon.json
# Si aparece "configuration OK", es correcto
  1. Reiniciar el demonio Docker
sudo systemctl restart docker

A partir de ahora, los nuevos contenedores heredarán estas configuraciones globales como valores predeterminados, a menos que se especifique lo contrario.

4. Configuración clave: Fijar el servidor DNS globalmente {#sec-d9c2238a423f}

4.1 ¿Por qué DNS global?

Si a menudo te encuentras con problemas como que los contenedores “extrañamente no encuentran APIs externas” o “no resuelven dominios internos”, la mayoría de las veces se debe a que dependen de la configuración/entorno DNS del host.

Por ejemplo:

  • Todo el equipo quiere usar Cloudflare DNS (1.1.1.1)
  • Existe un endpoint que solo se abre a través del servidor DNS interno de la empresa

En estos casos, en lugar de añadir dns: en docker-compose.yml para cada proyecto, es mucho más conveniente unificarlo directamente a nivel del demonio Docker.

4.2 Ejemplo de configuración (daemon.json)

{
  "dns": ["1.1.1.1", "8.8.8.8"]
}

Si ya tienes un daemon.json existente, simplemente añade el elemento "dns": [...] dentro del objeto raíz { ... }.

⚠️ Atención: La configuración DNS se refleja en /etc/resolv.conf dentro del contenedor. No se aplica inmediatamente a los contenedores ya en ejecución, sino que solo afectará a los nuevos contenedores que se inicien.

5. Configuración clave 2 – Controlador de logs y opciones globales {#sec-360ddebc7b6c}

Por defecto, los logs de los contenedores se almacenan en /var/lib/docker/containers/... a través del controlador json-file. Si lo cambias globalmente, podrás:

  • Formato de logs
  • Ubicación de almacenamiento de logs
  • Política de rotación de logs

...aplicarse de forma uniforme a todos los contenedores.

5.1 Controlador json-file predeterminado + rotación

El patrón más común es “usar json-file pero configurar la rotación para evitar que el disco se llene”.

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

Al configurarlo de esta manera:

  • El tamaño del archivo de log por contenedor es de un máximo de 10MB
  • Se mantienen un máximo de 5 archivos
  • Y los excedentes se eliminan automáticamente.

5.2 Controladores para la recolección centralizada de logs (fluentd, journald, etc.)

Si eres parte de un equipo de plataforma o infraestructura, es común que quieras enviar los logs de todos los contenedores a un sistema centralizado de logs.

Por ejemplo, si usas Fluentd:

{
  "log-driver": "fluentd",
  "log-opts": {
    "fluentd-address": "localhost:24224",
    "tag": "{{.Name}}"
  }
}

De esta forma, los logs de todos los contenedores se enviarán automáticamente a Fluentd sin necesidad de usar docker run --log-driver=... por separado.

Personalmente, también me gusta bastante el controlador journald. En entornos Linux basados en systemd, permite consolidar tanto los logs de aplicaciones como los logs de contenedores Docker en un solo lugar (journald), unificando así la consulta, el filtrado y las políticas de retención con un solo comando journalctl.

Si deseas utilizar journald como controlador global de logs, puedes configurarlo de la siguiente manera, por ejemplo:

{
  "log-driver": "journald",
  "log-opts": {
    "tag": "{{.Name}}"
  }
}

Dado que aquí estamos usando el nombre del contenedor como tag:

  • Puedes revisar rápidamente los logs en tiempo real con journalctl -f | grep {container_name}
  • Y combinarlo con opciones como --since "10m ago" para ver solo los logs a partir de un momento específico
  • O usar la opción -t (basada en tag/identificador) como en journalctl -f -t {container_name} para ver exclusivamente los logs de un contenedor específico.

Por supuesto, también es posible ver los logs por unidad, como con journalctl -u docker.service, pero filtrar por el nombre del contenedor es más intuitivo y requiere menos escritura, por lo que se usa mucho más en la práctica.

5.3 Relación con Compose / docker run

  • El log-driver + log-opts global actúa como “valor predeterminado”
  • Si se especifica logging: (Compose) o --log-driver, --log-opt (CLI) en un contenedor individual, solo ese contenedor anulará la configuración global.

Estratégicamente, se recomienda una configuración donde:

  • Los valores comunes estén en daemon.json
  • Y solo los servicios especiales tengan una anulación individual.

6. Configuración clave 3 – Configuración de red global: proxy, insecure registry, etc. {#sec-0d687ac65460}

Hay otras opciones de uso frecuente en la configuración global.

6.1 Configuración de proxy

Si solo puedes acceder al exterior a través de un proxy corporativo, en lugar de configurar variables de entorno cada vez, puedes establecer el proxy a nivel del demonio.

{
  "proxies": {
    "http-proxy": "http://proxy.example.com:3128",
    "https-proxy": "http://proxy.example.com:3128",
    "no-proxy": "localhost,127.0.0.1,.corp.example.com"
  }
}

De esta forma, el demonio Docker seguirá esta configuración de proxy al extraer imágenes o al usar la red durante la construcción.

6.2 Insecure registry

Si te encuentras en una situación donde es indispensable usar un registro sin TLS (por ejemplo, para desarrollo interno):

{
  "insecure-registries": ["my-registry.local:5000"]
}

Dado que puede ser un riesgo de seguridad, debes tener cuidado de usarlo solo en entornos de prueba internos.


7. Configuración clave 4 – Rango de red predeterminado, controlador de almacenamiento, etc. {#sec-3598d5fb02d3}

Opciones más orientadas a la infraestructura:

7.1 Personalización del rango de la red bridge predeterminada

Cuando quieres evitar que las IPs se solapen con tu VPN o red corporativa:

{
  "default-address-pools": [
    {
      "base": "10.20.0.0/16",
      "size": 24
    }
  ]
}

De esta forma, Docker utilizará el rango 10.20.x.0/24 al crear nuevas redes bridge.

7.2 Forzar el controlador de almacenamiento

El controlador de almacenamiento predeterminado puede variar según la distribución de Linux. Si tu equipo ha decidido usar solo overlay2:

{
  "storage-driver": "overlay2"
}

Los controladores de almacenamiento realmente compatibles varían según el OS/kernel, por lo que es imprescindible consultar la documentación de dockerd y la guía de tu distribución.


8. Si experimentas este 'déjà vu', es hora de adoptarlo {#sec-807a100451aa}

No necesitas ser un experto en infraestructuras complejas. Si recientemente has tenido alguna de las siguientes experiencias, es el momento perfecto para empezar a usar daemon.json.

  • Cada vez que inicias un nuevo proyecto, te encuentras buscando y pegando la configuración de logs en docker-compose.yml: Si estás copiando y pegando los ajustes de max-size y max-file de un código que escribiste ayer, ya estás perdiendo un tiempo valioso. Configúralo una sola vez de forma global y todos tus contenedores se iniciarán en modo 'dieta' automáticamente.
  • Un contenedor que funcionaba perfectamente en la oficina deja de tener internet cuando lo usas en una cafetería o con VPN: El clásico caso de “¡pero en mi local funciona!”. Si quieres que tus contenedores se comuniquen consistentemente con el exterior en cualquier entorno de red, sin depender de la configuración DNS del host, la fijación global de DNS es la solución.
  • Estás abrumado tratando de ajustar la configuración de innumerables nodos de servidor uno por uno: ¿Estás sufriendo por "bugs fantasma" causados por sutiles diferencias en la configuración de Docker en cada servidor? Despliega un solo archivo daemon.json y todos tus servidores funcionarán como un ejército, siguiendo las mismas reglas.

El momento óptimo para adoptar esta configuración es cuando te has cansado de repetir ajustes o de lidiar con problemas causados por cambios en el entorno.

Resumen

  • Los valores predeterminados globales de Docker se gestionan en daemon.json.
  • La ubicación suele ser /etc/docker/daemon.json
  • Ejemplos de configuraciones globales típicas:
    • DNS: "dns": ["1.1.1.1", "8.8.8.8"]
    • Controlador de logs: "log-driver": "json-file", "log-opts": {...}
    • Proxy, insecure registry, rango de red predeterminado, controlador de almacenamiento…
  • La configuración global es útil para evitar ajustes repetitivos y al desplegar muchos nodos en diversos entornos.

Si sigues utilizando las mismas opciones en docker-compose.yml o docker run, quizás sea el momento de trasladarlas a daemon.json.

imagen de la configuración del daemon.json de Docker