6.1 Introducción a la optimización de imágenes
Las imágenes de Docker, aunque son compactas, aún ocupan espacio. Por eso, reducir su tamaño es una tarea importante, y ayuda a mejorar el rendimiento, acelerar la descarga y el despliegue de contenedores, así como reducir los costos de almacenamiento. Se puede optimizar una imagen mejorando el Dockerfile, ya que se puede organizar de diferentes maneras. En esta clase vamos a ver varias estrategias y mejores prácticas para crear imágenes de Docker más optimizadas y ligeras.
¿Por qué es importante reducir el tamaño de las imágenes de Docker?
- Velocidad de despliegue: las imágenes más pequeñas se descargan más rápido desde el registro de Docker y se despliegan en contenedores más rápidamente, lo cual es especialmente importante en sistemas automatizados CI/CD.
- Uso eficiente de recursos: las imágenes ligeras ocupan menos espacio en disco, ahorran recursos de red al transferirse y permiten un uso más eficiente del poder computacional.
- Seguridad: las imágenes más pequeñas generalmente contienen menos componentes innecesarios, lo que reduce el riesgo de vulnerabilidades potenciales.
- Facilidad en las actualizaciones: actualizar imágenes ligeras es más rápido y consume menos recursos, lo que agiliza el proceso de mantenimiento.
6.2 Estrategias para reducir el tamaño de las imágenes Docker
1. Uso de imágenes base mínimas
La elección de la imagen base afecta directamente al tamaño final de la imagen Docker. Usar imágenes base mínimas, como alpine
, permite reducir significativamente el tamaño de la imagen.
Ejemplo:
Reemplazo de la imagen ubuntu
con alpine
:
# FROM ubuntu:20.04
FROM alpine:3.12
alpine
es una distribución ligera de Linux que ocupa alrededor de 5 MB, mientras que la imagen ubuntu
puede ocupar cientos de megabytes.
2. Minimización del número de capas
Cada instrucción en un Dockerfile añade una nueva capa a la imagen. Combinar varias instrucciones en un solo comando RUN
reduce el número de capas, ayudando a disminuir el tamaño total de la imagen.
Ejemplo:
Antes de la optimización:
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
RUN rm -rf /var/lib/apt/lists/*
Después de la optimización:
RUN apt-get update && apt-get install -y curl git && rm -rf /var/lib/apt/lists/*
Eliminar la caché del gestor de paquetes (rm -rf /var/lib/apt/lists/*)
reduce aún más el tamaño de la imagen al eliminar archivos temporales creados durante la instalación.
3. Eliminación de archivos temporales
Eliminar archivos temporales y datos innecesarios tras instalar paquetes ayuda a mantener la imagen limpia y ligera.
Ejemplo:
RUN apt-get update && apt-get install -y curl git && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
4. Uso de .dockerignore
El archivo .dockerignore
ayuda a excluir archivos y directorios innecesarios del contexto de construcción, lo que reduce el tamaño de la imagen y acelera el proceso de construcción.
Ejemplo .dockerignore
:
node_modules
dist
*.log
Dockerfile*
.dockerignore
5. Construcción multietapa (multi-stage builds)
Las construcciones multietapa permiten usar varias imágenes intermedias para crear una imagen final ligera que solo contiene los archivos y dependencias necesarias.
Ejemplo:
# Fase de construcción
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Fase final
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
En este ejemplo, la primera etapa construye la aplicación, mientras que la fase final solo usa los resultados de la construcción, lo que reduce el tamaño de la imagen final.
6. Optimización de instalación de paquetes
Instalar solo los paquetes necesarios y usar opciones de los gestores de paquetes para instalaciones mínimas ayuda a reducir el tamaño de la imagen.
Ejemplo:
Uso de la opción --no-install-recommends
en apt-get
:
RUN apt-get update && apt-get install -y --no-install-recommends curl git && \
rm -rf /var/lib/apt/lists/*
7. Compresión y minimización de datos
Usar herramientas para comprimir y minimizar datos ayuda a reducir el tamaño de la imagen.
Ejemplo:
Compresión de archivos de texto y registros de logs:
RUN gzip /path/to/large/file.log
8. Eliminación de bibliotecas y dependencias no utilizadas
Eliminar bibliotecas y dependencias no utilizadas tras instalar los paquetes necesarios ayuda a mantener la imagen ligera.
Ejemplo:
Para aplicaciones Python:
RUN pip install --no-cache-dir -r requirements.txt
6.3 Ejemplos de Dockerfile optimizados
Ejemplo 1: Dockerfile optimizado para Node.js
FROM node:14-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
Este ejemplo utiliza una construcción de varias etapas. Primero, la aplicación se construye en una etapa intermedia, y luego solo los resultados de la construcción se copian en la imagen final basada en Nginx.
Ejemplo 2: Dockerfile optimizado para Python
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]
En este ejemplo, se utiliza una imagen base ligera python:3.9-slim
. La instalación de las dependencias se separa en un paso independiente, lo que permite utilizar la caché de Docker si el archivo requirements.txt
no ha cambiado.
GO TO FULL VERSION