Escribir y optimizar Dockerfiles
Qué cubre este artículo
- Estructura de un Dockerfile.
- Instrucciones clave y su orden.
- Capas, caché y tamaño de imagen.
- Seguridad y compilaciones limpias.
- Errores comunes y soluciones.
Introducción: Escribir y optimizar Dockerfiles
Un Dockerfile es la receta para crear una imagen Docker. Define cuál es la imagen base, qué archivos se copian, qué comandos se ejecutan y cómo inicia el contenedor. Un Dockerfile bien escrito produce imágenes pequeñas, seguras y que se compilan rápidamente. Uno mal escrito genera tiempos de compilación prolongados, imágenes enormes y vulnerabilidades de seguridad.
Este artículo explica los fundamentos, las instrucciones clave y las mejores prácticas para Dockerfiles limpios.
Términos clave
- FROM: Imagen base.
- RUN: Ejecutar un comando.
- COPY: Copiar archivos.
- ADD: Copiar y desempaquetar archivos.
- CMD: Comando predeterminado al iniciar.
- ENTRYPOINT: Comando de inicio fijo.
- WORKDIR: Directorio de trabajo.
- ENV: Variable de entorno.
- EXPOSE: Declarar un puerto.
- USER: Cambiar de usuario.
- Layer: Capa en la imagen.
- Cache: Almacenamiento temporal para compilaciones.
Estructura básica
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
Elegir FROM
| Imagen | Tamaño | Uso |
|---|---|---|
ubuntu | grande | Compatibilidad |
debian:slim | medio | Versátil |
alpine | pequeño | Compacta, pero musl |
distroless | muy pequeño | Mínima, sin shell |
Recomendación: Usar imágenes slim oficiales o distroless para contenedores en producción.
Respetar el orden
Docker almacena en caché las capas. Copia primero los archivos que cambian con menos frecuencia:
- Imagen base.
- Archivos de dependencias.
- Instalar dependencias.
- Copiar código fuente.
- Pasos de compilación.
- Comando de ejecución.
Incorrecto:
COPY . .
RUN npm ci
Correcto:
COPY package*.json ./
RUN npm ci
COPY . .
COPY vs ADD
COPYsimplemente copia archivos.ADDpuede procesar URLs y archivos Tar.- En la mayoría de los casos,
COPYes más seguro y predecible.
Minimizar capas
Cada instrucción RUN, COPY y ADD crea una capa. Menos capas significan imágenes más pequeñas:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates && \
rm -rf /var/lib/apt/lists/*
Reducir el tamaño de la imagen
- Usar
.dockerignore. - Instalar solo dependencias de producción.
- Eliminar herramientas de compilación.
- Usar compilaciones multietapa.
- No copiar archivos innecesarios.
Ejemplo de .dockerignore:
node_modules
.git
.env
Dockerfile
README.md
tests
Seguridad
- Usar un usuario sin permisos de root:
RUN useradd -m appuser
USER appuser
- No incluir secretos en el Dockerfile.
- No guardar contraseñas en variables de entorno.
- Mantener permisos mínimos.
- Usar un sistema de archivos de solo lectura cuando sea posible.
CMD y ENTRYPOINT
CMD es el comando predeterminado, ENTRYPOINT es el comando fijo. Combinación:
ENTRYPOINT ["node"]
CMD ["server.js"]
Verificaciones de salud
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Comando de compilación
docker build -t mein-image:1.0 .
Forzar la compilación sin caché
docker build --no-cache -t mein-image:1.0 .
Logs y configuración
- Enviar logs a
stdout/stderr. - Configuración a través de variables de entorno.
- No incluir rutas fijas en las imágenes.
Errores comunes
- Todo en una sola capa: imágenes grandes.
- Herramientas de compilación en la imagen de ejecución: riesgos de seguridad.
- Secretos en variables de entorno: visibles en imágenes o logs.
- Versión FROM incorrecta: usar
latesten lugar de tags fijos. - Falta
.dockerignore: archivos innecesarios en la imagen. - Permisos incorrectos: el contenedor se ejecuta como root.
- CMD en forma de shell: las señales no se transmiten correctamente.
Enlaces y referencias adicionales
- BotServ.de Docker Compilaciones multietapa
- BotServ.de Comandos Docker
- BotServ.de Optimización de imágenes Docker
- BotServ.de Seguridad Docker
FAQ: Dockerfile
¿Qué es un Dockerfile? Un archivo de texto con instrucciones para compilar una imagen Docker.
¿Debo usar COPY . .?
Solo con .dockerignore, de lo contrario archivos innecesarios terminan en la imagen.
¿Qué es mejor: Alpine o Debian Slim? Debian Slim tiene mejor compatibilidad, Alpine es más pequeño pero basado en musl.
¿Cómo reduzco el tiempo de compilación?
Respeta el orden de las capas, aprovecha el caché y configura .dockerignore.
¿Por qué usar un usuario sin permisos de root? Reduce el riesgo si un contenedor es comprometido.
Fuentes y literatura adicional
- Referencia de Dockerfile: https://docs.docker.com/reference/dockerfile/
- Mejores prácticas de Docker: https://docs.docker.com/develop/dev-best-practices/
- BuildKit: https://docs.docker.com/build/buildkit/
Resumen: Escribir y optimizar Dockerfiles
Un buen Dockerfile es clave para compilaciones rápidas, imágenes pequeñas y contenedores seguros. Lo importante es el orden correcto de las instrucciones, el caché efectivo, compilaciones multietapa, .dockerignore, usuarios sin permisos de root y tags de imagen fijos. Quienquiera que siga estos principios evitará problemas típicos y compilará imágenes Docker que funcionen bien tanto en homelab como en producción.


