Explorando Docker, Parte 4: Reduciendo el tamaño de las imágenes y acelerando su ensamblaje

En esta parte de la traducción de la serie Docker, hablaremos sobre cómo optimizar los tamaños de imagen y acelerar el ensamblaje. En materiales anteriores, comparamos imágenes de Docker con pizza, términos con donas e instrucciones de Dockerfile con rosquillas. Hoy no habrá horneado. Es hora de ponerse a dieta.

→ Parte 1: lo básico
→ Parte 2: términos y conceptos
→ Parte 3: archivos Dockerfile
→ Parte 4: reducir el tamaño de las imágenes y acelerar su ensamblaje
→ Parte 5: equipos
→ Parte 6: trabajar con datos


Para comprender de qué vamos a hablar aquí, le será útil actualizar la memoria de lo que se discutió en la tercera parte de esta serie de materiales. A saber, allí hablamos sobre las instrucciones del archivo Dockerfile. Conocer estas instrucciones y las características de Docker que discutimos hoy lo ayudará a optimizar sus archivos de imagen de Docker.

Almacenamiento en caché


Una de las fortalezas de Docker es el almacenamiento en caché. Gracias a este mecanismo, el ensamblaje de imágenes se acelera.

Al ensamblar una imagen Docker, sigue las instrucciones del Dockerfile, siguiéndolas en orden. En el proceso de analizar las instrucciones, Docker verifica su propia memoria caché en busca de imágenes, que es lo que obtenemos en las etapas intermedias del ensamblaje de otras imágenes. Si se pueden encontrar tales imágenes, entonces el sistema puede usarlas sin perder tiempo volviendo a crearlas.

Si se invalida el caché, se ejecuta la instrucción durante la cual sucedió, creando una nueva capa sin usar el caché. Lo mismo sucede al ejecutar las instrucciones que le siguen.

Como resultado, si durante la ejecución de las instrucciones del Dockerfile resulta que la imagen base está en el caché, entonces se usa esta imagen del caché. Esto se llama un acierto de caché. Si la imagen base no está en el caché, entonces todo el proceso de ensamblaje de la imagen ocurrirá sin usar el caché.

Luego, la siguiente instrucción se compara con todas las imágenes del caché, que se basan en la misma imagen básica que ya se encuentra en el caché. Cada imagen intermedia en caché se verifica para ver si contiene lo que se creó con la misma instrucción. Si no se puede encontrar una coincidencia, esto se denomina "error de caché" y el caché se considera no válido. Lo mismo sucede hasta que se procesa todo el Dockerfile.

La mayoría de las nuevas instrucciones se comparan simplemente con lo que ya está en las imágenes intermedias. Si el sistema logra encontrar una coincidencia, el ensamblaje usa lo que ya está en la caché.

Usar un caché puede acelerar el ensamblaje de imágenes, pero hay un problema. Por ejemplo, si se encuentra una instrucción RUN pip install -r requirements.txt required.txt en un Dockerfile, entonces Docker busca la misma instrucción en su caché local de imágenes intermedias. Sin embargo, el contenido de las versiones anterior y nueva del archivo require.txt no se compara.

Esto puede generar problemas si se agrega información sobre los nuevos paquetes a requirements.txt , después de lo cual, al crear la imagen actualizada, para instalar un nuevo conjunto de paquetes, debe ejecutar nuevamente la instrucción RUN pip install . Pronto hablaremos sobre cómo lidiar con este problema.

A diferencia de otras instrucciones de Docker, al ejecutar las instrucciones ADD y COPY , Docker necesita verificar el contenido del archivo o archivos para determinar si se puede usar el caché al crear la imagen. Es decir, la suma de verificación de los archivos mencionados en estas instrucciones se compara con la suma de verificación de los archivos que están en las imágenes intermedias que ya están en la caché. Si el contenido de los archivos o sus metadatos ha cambiado, la memoria caché se invalida.

Aquí hay algunos consejos para aprovechar el caché de Docker:

  • El almacenamiento en caché se puede deshabilitar pasando el interruptor --no-cache=True al docker build .
  • Si va a realizar cambios en las instrucciones de Dockerfile, cada capa creada por las instrucciones que vienen después de las cambiadas se volverá a montar con bastante frecuencia, sin usar un caché. Para aprovechar el almacenamiento en caché, coloque las instrucciones que es muy probable que cambien, lo más cerca posible del final del Dockerfile.
  • Combine los comandos RUN apt-get update e apt-get install en cadenas para evitar problemas asociados con el uso incorrecto de la memoria caché.
  • Si usa administradores de paquetes, como pip , con el archivo require.txt, entonces siga el esquema a continuación para excluir el uso de imágenes intermedias obsoletas del caché que contiene el conjunto de paquetes enumerados en la versión anterior del archivo require.txt. Así es como se ve:

     COPY requirements.txt /tmp/ RUN pip install -r /tmp/requirements.txt COPY . /tmp/ 

Si conoce otras formas de lidiar con el "problema de requisitos.txt", puede informar sobre ellas en los comentarios.

Reducir el tamaño de las imágenes.


▍ Selección cuidadosa de la imagen básica


Las imágenes de Docker pueden ser bastante grandes. Esto contradice el deseo bien fundamentado de la persona que los crea de hacerlos lo más compactos posible, lo que facilitará su descarga desde un repositorio remoto y tendrá un efecto beneficioso en la cantidad de espacio libre en la computadora en la que están cargados. Hablemos sobre cómo reducir su tamaño.


En lugar de rosquillas y rosquillas, ahora comeremos verduras

Una forma de reducir el tamaño de las imágenes es seleccionar cuidadosamente las imágenes básicas y su posterior ajuste.

Por ejemplo, la imagen básica de Alpine es una distribución completa de un sistema operativo similar a Linux, que contiene un mínimo de paquetes adicionales. Su tamaño es de aproximadamente 5 megabytes. Sin embargo, crear su propia imagen basada en Alpine requerirá mucho tiempo para equiparlo con todo lo necesario para garantizar el funcionamiento de una determinada aplicación.

También hay versiones especializadas de la imagen básica de Alpine. Por ejemplo, la imagen correspondiente del repositorio de Python en el que está empaquetado el script print("hello world") pesa aproximadamente 78.5 MB. Aquí está el Dockerfile para construir tal imagen:

 FROM python:3.7.2-alpine3.8 COPY . /app ENTRYPOINT ["python", "./app/my_script.py", "my_var"] 

Al mismo tiempo, Docker Hub dice que esta imagen básica tiene un tamaño de 29 MB. El tamaño de una imagen basada en esta imagen base aumenta al descargar e instalar Python.

Además de usar imágenes básicas basadas en Alpine, puede reducir el tamaño de las imágenes mediante el uso de la tecnología de ensamblaje de etapas múltiples.

▍ Ensamblaje de imágenes en varias etapas


El Dockerfile, que describe el ensamblaje en varias etapas de una imagen, usa varias instrucciones FROM . El creador de dicha imagen puede configurar una copia selectiva de archivos llamados artefactos de compilación de un nivel de compilación a otro. Al mismo tiempo, es posible deshacerse de todo lo que no se necesita en la imagen final. Gracias a este método, puede reducir el tamaño de la imagen terminada.

Así es como funciona cada instrucción FROM :

  • Ella comienza un nuevo paso de construcción.
  • No depende de lo que se creó en el paso de compilación anterior.
  • Ella puede usar una imagen básica que sea diferente de la utilizada en el paso anterior.

Aquí hay un ejemplo modificado de un Dockerfile de la documentación de Docker que describe una compilación de varias etapas.

 FROM golang:1.7.3 AS build WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=build /go/src/github.com/alexellis/href-counter/app . CMD ["./app"] 

Tenga en cuenta que le dimos el nombre de la primera etapa del ensamblado, especificándolo después de la declaración FROM . Nos referimos a la fase de compilación nombrada en la COPY --from= continuación en el Dockerfile.

El uso del proceso de ensamblaje de imágenes en varias etapas tiene sentido en algunos casos cuando tiene que crear muchos contenedores para el entorno de producción. El ensamblaje en varias etapas le permite minimizar el tamaño de la imagen terminada. Pero a veces este enfoque complica el soporte de las imágenes. Por lo tanto, probablemente no utilizará el ensamblaje de imágenes en varias etapas en los casos en que pueda prescindir de él. Puede leer sobre las características de esta tecnología aquí y aquí .

Como puede ver, el ensamblaje en varias etapas es una tecnología interesante, pero no es adecuada para todos los casos. La misma forma de reducir el tamaño de las imágenes, que discutiremos a continuación, se puede recomendar a absolutamente todos.

▍ archivo .dockerignore


Absolutamente todos los que quieran aprender Docker necesitan saber acerca de los archivos .dockerignore . Estos archivos son similares a los archivos .gitignore . Contienen una lista de archivos y carpetas, en forma de nombres o plantillas que Docker debe ignorar durante el ensamblaje de la imagen.

Este archivo se coloca donde se encuentra el Dockerfile y todo lo demás que se incluye en el contexto del ensamblaje de la imagen.

Cuando ejecuta el docker build Docker, que inicia el ensamblaje de la imagen, Docker comprueba la carpeta en busca de la presencia del archivo .dockerignore . Si se puede encontrar dicho archivo, entonces este archivo se analiza y las reglas de la función Match() del paquete filepath Go y algunas de sus propias reglas de Docker se utilizan para determinar la lista de archivos que se ignorarán.

Entonces, por ejemplo, si se encuentra una plantilla de la forma *.jpg en el archivo .dockerignore , al crear una imagen, los archivos con cualquier nombre y con la extensión .jpg serán ignorados. Si la cadena de videos en el archivo, el sistema ignorará la carpeta de videos y todo su contenido.

Al compilar un archivo .dockerignore , puede comentarlo usando el símbolo # .

.dockerignore es lo que el archivo .dockerignore le da a cualquiera que cree imágenes de Docker:

  • Esto le permite excluir de los archivos de imagen que contienen información confidencial como inicios de sesión y contraseñas.
  • Esto le permite reducir el tamaño de la imagen. Cuanto más pequeños sean los archivos en la imagen, más pequeño será su tamaño y más rápido será posible trabajar con ellos.
  • Esto hace posible reducir la cantidad de razones para invalidar el caché cuando se ensamblan imágenes similares. Por ejemplo, si durante el reensamblaje de la imagen algunos archivos de servicio del proyecto cambian, como los archivos de registro, debido a que los datos almacenados en el caché se invalidan, en esencia, sin razón, esto ralentiza el ensamblaje de las imágenes.

.dockerignore leer más sobre el archivo .dockerignore en la documentación de Docker.

Investigación de tamaño de imagen


Hablemos sobre cómo usar las herramientas de línea de comandos para averiguar los tamaños de las imágenes y contenedores de Docker.

  • Para averiguar el tamaño aproximado de un contenedor en ejecución, puede usar un comando del formulario docker container ls -s .
  • El docker image ls muestra los tamaños de docker image ls .
  • Puede usar el docker image history my_image:my_tag averiguar los tamaños de las imágenes intermedias a partir de las cuales se ensambla una determinada imagen.
  • La docker image inspect my_image:tag permite encontrar información detallada sobre la imagen, incluido el tamaño de cada una de sus capas. Las capas son ligeramente diferentes de las imágenes intermedias que conforman la imagen final, pero, en la mayoría de los casos, pueden considerarse entidades idénticas. Aquí hay un buen material sobre los detalles de la estructura interna de las imágenes de Docker.
  • Para examinar el contenido de los contenedores, puede instalar el paquete de buceo .

Ahora que hemos discutido las posibilidades de reducir el tamaño de las imágenes, le presento ocho recomendaciones sobre cómo reducir el tamaño de las imágenes y acelerar el proceso de ensamblarlas.

Recomendaciones para reducir el tamaño de las imágenes y acelerar el proceso de ensamblaje


  1. Siempre que sea posible, use imágenes oficiales como imágenes básicas. Las imágenes oficiales se actualizan regularmente, son más seguras que las imágenes informales.
  2. Para recopilar imágenes tan compactas como sea posible, use imágenes básicas basadas en Alpine Linux.
  3. Si usa apt , combine los comandos apt-get update y apt-get install en una declaración RUN . Además, combine los comandos de instalación de paquetes en una sola instrucción. Liste los paquetes alfabéticamente en varias líneas, separando la lista con \ . Por ejemplo, podría verse así:

     RUN apt-get update && apt-get install -y \   package-one \   package-two \   package-three && rm -rf /var/lib/apt/lists/* 

    Este método reduce la cantidad de capas que se deben agregar a la imagen y ayuda a mantener el código del archivo de forma decente.
  4. Incluya una construcción como && rm -rf /var/lib/apt/lists/* al final de la instrucción RUN utilizada para instalar paquetes. Esto borrará el caché apt y hará que no se guarde en la capa formada por el comando RUN . Los detalles sobre esto se pueden encontrar en la documentación .
  5. Use sus capacidades de almacenamiento en caché con prudencia colocando comandos en el Dockerfile que es muy probable que cambien cerca del final del archivo.
  6. Use el archivo .dockerignore .
  7. Eche un vistazo a la dive , una gran herramienta para explorar imágenes de Docker que ayuda a reducir su tamaño.
  8. No instale paquetes que se puedan prescindir.

Resumen


Ahora sabe cómo hacer que las imágenes de Docker se ensamblen rápidamente, se carguen rápidamente desde los repositorios y no ocupen demasiado espacio en la computadora. La próxima vez hablaremos sobre los equipos Docker.

Estimados lectores! ¿Ha encontrado problemas con los mecanismos de almacenamiento en caché al crear imágenes de Docker?

Source: https://habr.com/ru/post/440658/


All Articles