Los contenedores le permiten empaquetar su aplicación de forma portátil que puede ejecutarse en muchos entornos. La plataforma de contenedores más popular es Docker.
Este tutorial le explicará cómo utilizar la memoria caché de compilación de Docker a su favor.
Caché de compilación de Docker
La creación de imágenes debe ser rápida, eficiente y confiable. El concepto de imágenes Docker viene con capas inmutables. Cada comando que ejecuta da como resultado una nueva capa que contiene los cambios en comparación con la capa anterior.
Todas las capas construidas previamente se almacenan en caché y se pueden reutilizar. Pero, si su instalación depende de recursos externos, la caché de Docker puede causar problemas.
Cómo aprovechar la caché de compilación de Docker
Para comprender los problemas de compilación de caché de Docker, construyamos una aplicación nginx Docker personalizada simple. Antes de compilar la imagen, cree un Dockerfile que actualice las bibliotecas y agregue una página de inicio personalizada:
FROM nginx:1.21.6
# Update all packages
RUN apt-get update && apt-get -y upgrade
# Use a custom startpage
RUN echo '<html><bod>My Custom Startpage</body></html>' > /usr/share/nginx/html/index.html
Ahora puede crear la imagen de Docker:
$ docker build -t my-custom-nginx .
=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e12... 5.8s
=> [2/3] RUN apt-get update && apt-get -y upgrade 3.6s
=> [3/3] RUN echo '<html><bod>My Custom Startpage... 0.2s
=> exporting to image 0.1s
=> exporting layers 0.1s
=> writing image 0.0s
=> naming to docker.io/library/my-custom-nginx
[+] Building 11.3s (7/7) FINISHED
En este ejemplo, eliminé algunos resultados para mejorar la legibilidad. Si construyes la imagen la primera vez, verás que lleva bastante tiempo, en mi caso 11.3s
.
Un paso largo de ejecución es apt-get update && apt-get -y upgrade
dependiendo de cuántas dependencias se actualicen y qué tan rápida sea su velocidad de Internet. Comprueba si hay actualizaciones de paquetes en el sistema operativo y las instala si están disponibles.
Ahora, lo ejecuta de nuevo y se beneficia de la memoria caché de compilación de Docker:
$ docker build -t my-custom-nginx .
=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1… 0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade 0.0s
=> CACHED [3/3] RUN echo '<html><bod>My Custom Startpage... 0.0s
=> exporting to image 0.0s
=> exporting layers 0.0s
=> writing image 0.0s
=> naming to docker.io/library/my-custom-nginx
Building 1.1s (7/7) FINISHED
Esta vez, la creación de la imagen es muy rápida porque puede reutilizar todas las imágenes creadas anteriormente. Cuando personaliza su página de inicio en Dockerfile, ve cómo se ve afectado el comportamiento del almacenamiento en caché:
FROM nginx:1.21.6
# Update all packages
RUN apt-get update && apt-get -y upgrade
# Use a custom startpage
RUN echo '<html><bod>New Startpage</body></html>' > /usr/share/nginx/html/index.html
Ahora, construye la imagen de nuevo:
$ docker build -t my-custom-nginx .
=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1… 0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade 0.0s
=> [3/3] RUN echo '<html><bod>My Custom Startpage... 0.2s
=> exporting to image 0.0s
=> exporting layers 0.0s
=> writing image 0.0s
=> naming to docker.io/library/my-custom-nginx
Building 2.1s (7/7) FINISHED
Esta vez solo reconstruyó la última capa porque reconoció que RUN
el comando había cambiado. Sin embargo, reutilizó el intenso segundo paso de compilación y no actualizó las dependencias del sistema operativo.
El comportamiento de almacenamiento en caché es inteligente. Una vez que se necesita reconstruir 1 paso, cada paso subsiguiente se vuelve a construir. Por lo tanto, es bueno colocar las partes que cambian con frecuencia al final de un Dockerfile
para reutilizar capas de construcción anteriores.
Aún así, tal vez desee forzar una reconstrucción de una capa almacenada en caché para forzar una actualización del paquete. Forzar una reconstrucción puede ser necesario porque desea mantener su aplicación segura y usar las actualizaciones más recientes cuando estén disponibles.
Cómo usar la compilación de Docker --no-cache
Opción
Puede haber diferentes razones para deshabilitar el caché de compilación. Puede reconstruir la imagen a partir de la imagen base sin usar capas almacenadas en caché utilizando --no-cache
opción.
$ docker build -t my-custom-nginx .
=> CACHED [1/3] FROM docker.io/library/nginx:1.21.6@sha256:... 0.0s
=> [2/3] RUN apt-get update && apt-get -y upgrade 3.5s
=> [3/3] RUN echo '<html><bod>My Custom Startpage... 0.2s
=> exporting to image 0.1s
=> exporting layers 0.0s
=> writing image 0.0s
=> naming to docker.io/library/my-custom-nginx
Building 5.5s (7/7) FINISHED
Se construyeron y utilizaron nuevas capas. La docker build
ejecuta ambos comandos esta vez, que viene con un enfoque de todo o nada. O proporciona el --no-cache
opción que ejecuta todos los comandos, o almacenará en caché tanto como sea posible.
Cómo utilizar los argumentos de Docker para la prevención de caché
Otra opción permite proporcionar un pequeño punto de partida en el Dockerfile. Necesitas editar tu Dockerfile así:
FROM nginx:1.21.6
# Update all packages
RUN apt-get update && apt-get -y upgrade
# Custom cache invalidation
ARG CACHEBUST=1
# Use a custom startpage
RUN echo '<html><bod>New Startpage</body></html>' > /usr/share/nginx/html/index.html
Agregas un CACHEBUST
argumento a su Dockerfile en la ubicación en la que desea aplicar una reconstrucción. Ahora, puede crear la imagen de Docker y proporcionar un valor siempre diferente que haga que se vuelvan a ejecutar todos los siguientes comandos:
$ docker build -t my-custom-nginx --build-arg CACHEBUST=$(date +%s) .
=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1... 0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade 0.0s
=> [3/3] RUN echo '<html><bod>My Custom Startpage... 0.3s
=> exporting to image 0.0s
=> exporting layers 0.0s
=> writing image 0.0s
=> naming to docker.io/library/my-custom-nginx
Building 1.0s (7/7) FINISHED
Proporcionando --build-arg CACHEBUST=$(date +%s)
, establece el parámetro en un valor siempre diferente que hace que todas las capas siguientes se reconstruyan.