Optimizar imágenes Docker con pruebas y medidas

Índice de contenido
  1. Mide una referencia
  2. Limita el contexto
  3. Construcción por etapas
  4. Orden de capas y caché
  5. Usuario y permisos
  6. Compara con pruebas
  7. Base, digest y mantenimiento
  8. Preguntas frecuentes
    1. ¿Multi-stage siempre reduce mucho el tamaño?
    2. ¿Una imagen menor tiene menos vulnerabilidades?
    3. ¿Borrar archivos en otro RUN elimina su peso anterior?
  9. En pocas palabras
  10. Conclusión
  11. Fuentes y documentación

Para optimizar una imagen Docker, identifica qué archivos y dependencias necesita realmente la aplicación. Después revisa contexto, orden de capas y construcción por etapas. No cambies de base solo para obtener un número menor sin comprobar comportamiento.

Esta guía utiliza una aplicación Node como ejemplo. Adapta compilación y pruebas a tu proyecto y arquitectura.

Mide una referencia

Registra versión, arquitectura, tamaño y tiempo de construcción bajo condiciones conocidas. Distingue una construcción con caché de otra limpia.

No publiques porcentajes de mejora sin explicar qué cambió. Un resultado medido en una computadora no garantiza el mismo ahorro en otra red o plataforma.

Limita el contexto

Un .dockerignore puede excluir archivos que no deben llegar al build:

node_modules
.git
.env
secrets
*.pem
npm-debug.log

Revisa que no excluyas archivos necesarios. También comprueba que no queden otras credenciales con nombres diferentes: esta lista no descubre secretos automáticamente.

Copiar un secreto y borrarlo después no garantiza que desaparezca de capas anteriores. Utiliza mecanismos de build secretos cuando sean necesarios y compatibles.

Construcción por etapas

Para una aplicación JavaScript sin compilación adicional:

FROM node:24-slim AS dependencias
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM node:24-slim AS ejecucion
ENV NODE_ENV=production
WORKDIR /app
COPY --from=dependencias /app/node_modules ./node_modules
COPY --chown=node:node src ./src
USER node
EXPOSE 3000
CMD ["node", "src/index.js"]

Si utilizas TypeScript, bundling o módulos nativos, necesitas etapas y archivos adicionales. No copies este ejemplo suponiendo que ejecuta un script build que no existe.

Orden de capas y caché

Copiar primero manifiestos de dependencias permite reutilizar su instalación cuando solo cambia código. Eso funciona si el lockfile representa correctamente el proyecto.

Una caché rápida no debe ocultar dependencias desactualizadas. Separa la optimización de builds del proceso de actualización de la base y bibliotecas.

Usuario y permisos

Ejecutar con un usuario limitado reduce privilegios, pero la aplicación debe poder leer y escribir en las rutas apropiadas. No le otorgues permisos globales para compensar un directorio mal elegido.

Dentro de un contenedor, una aplicación web puede necesitar escuchar en una interfaz alcanzable por su red; la restricción externa se define también al publicar puertos. Son capas diferentes.

Compara con pruebas

docker build -t app-optimizada:lab .
docker image inspect app-optimizada:lab
docker history app-optimizada:lab

Inspecciona sin compartir configuraciones sensibles. Ejecuta tests, inicio y funciones críticas con la misma carga. La ausencia de herramientas de depuración puede ser intencional, pero debes conservar un método de diagnóstico.

Base, digest y mantenimiento

Una base mínima puede mejorar el peso y complicar módulos o certificados. Compara slim, Alpine u otras opciones según soporte real.

Fijar un digest facilita reproducibilidad; no reemplaza actualizar. Documenta cómo revisarás nuevas bases y vulnerabilidades.

Preguntas frecuentes

¿Multi-stage siempre reduce mucho el tamaño?

No. Depende de qué componentes excluyes de la etapa final. Si copias todo de nuevo, puedes conservar el mismo peso.

¿Una imagen menor tiene menos vulnerabilidades?

No necesariamente. Importan componentes, versiones, configuración y explotación posible; tamaño no es una medida suficiente.

¿Borrar archivos en otro RUN elimina su peso anterior?

No de forma general en capas ya creadas. Diseña el build para no incorporarlos o utiliza mecanismos apropiados.

En pocas palabras

Optimizar una imagen significa reducir trabajo y componentes innecesarios manteniendo funcionalidad y soporte. Las capas y el contexto importan tanto como la elección de base.

Conclusión

Conserva una referencia y repite las mismas pruebas después de optimizar. Si ahorras espacio pero pierdes compatibilidad, mantenimiento o diagnóstico, revisa el equilibrio.

Para continuar, revisa Docker: qué es y cómo usarlo para ejecutar contenedores y Cómo instalar Docker en Ubuntu 24.04: guía práctica paso a paso.

Fuentes y documentación

Documentación de docs.docker.com.

Documentación de docs.docker.com.

Subir

Descubre más de Sergio Caballero

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Continuar leyendo