Dockerfiles a dieta: imágenes más pequeñas y builds más rápidos

Dockerfiles a dieta: imágenes más pequeñas y builds más rápidos

Pocas cosas delatan tanto la madurez de un equipo como sus Dockerfiles. Imágenes de más de un gigabyte, builds de 15 minutos y contenedores corriendo como root son más comunes de lo que parece. En esta entrada comparto los trucos que aplico para conseguir imágenes pequeñas, seguras y rápidas de construir.

1. Multi-stage builds: compila en un sitio, ejecuta en otro

El truco con más impacto. La imagen final solo necesita el binario o los artefactos, no el compilador ni las dependencias de build:

FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html

Con este patrón he visto imágenes pasar de 1,2 GB a menos de 60 MB sin cambiar una línea de la aplicación.

2. El orden de las capas importa (y mucho)

Docker cachea capa a capa: en cuanto una cambia, todas las siguientes se reconstruyen. Por eso las dependencias van antes que el código:

  • Copia primero package.json / requirements.txt / go.mod e instala dependencias.
  • Copia el código fuente después: es lo que más cambia.
  • Deja para el final lo que cambia en cada build (metadatos, versión).

3. Imágenes base mínimas

  • alpine: ligera y suficiente para la mayoría de casos (ojo con musl si compilas nativo).
  • distroless (de Google): sin shell ni gestor de paquetes; superficie de ataque mínima, ideal para producción.
  • slim: buen punto medio cuando alpine da problemas de compatibilidad.

4. No olvides lo básico

  • .dockerignore: excluye .git, node_modules, artefactos y secretos. Menos contexto = builds más rápidos.
  • Usuario no root: añade USER app al final. Si te comprometen el contenedor, que no sea con privilegios.
  • Una responsabilidad por contenedor: si necesitas cron + web + worker, son tres contenedores, no uno.
  • Escanea las imágenes: integra Trivy o Grype en el pipeline y bloquea vulnerabilidades críticas.
  • Etiquetas inmutables: despliega por digest o versión semántica, nunca confíes en latest.

Conclusión

Un buen Dockerfile no es cuestión de estética: son builds más rápidos, despliegues más ágiles, menos superficie de ataque y menos costes de almacenamiento y red. La próxima vez que un build te parezca lento o una imagen enorme, revisa estos puntos; casi siempre hay una victoria fácil esperando.

¿Cuál es el tamaño de tu imagen más grande en producción? Confiesa en los comentarios. 😊