Práctica de ajuste de imágenes de Docker para la construcción del proyecto Java SpringBoot

        Vi este documento en línea y pensé que era muy bueno. Lo reimprimo aquí para aprender principalmente las ideas sobre el uso del almacenamiento en caché jerárquico y el procesamiento del tamaño de la imagen en este artículo.

Reimpreso de: Construcción del proyecto Java SpringBoot Práctica de ajuste de imágenes de Docker | Xiaodudin Technology Stack

PD: Se ha verificado en la práctica de producción para resolver el problema de que en el entorno de producción, la velocidad de la red y el ancho de banda son pequeños, y cada inserción y extracción de la imagen afecta el servicio en línea. La imagen se construye de acuerdo con el método de este artículo. Además de tirar, empujar y construir lentamente la imagen por primera vez, la segunda, la segunda, la tercera... las veces tuvieron un tamaño de cientos de K. La velocidad fue muy rápida y la construcción, el embalaje, y empujar se completaron en unos pocos segundos.

Prefacio:

        En la era anterior de los microservicios Spring Cloud, los "paquetes Jar" eran la base de los servicios. Cada servicio estaba empaquetado en un Jar para las interrelaciones y llamadas entre servicios. Ahora, con la popularidad de Kubernetes, ha cambiado a una imagen y un servicio, y Kubernetes se basa en la orquestación unificada de imágenes para gestionar los servicios de manera uniforme. En el proceso de práctica de los microservicios de Kubernetes, el más expuesto es definitivamente la imagen de Docker. Dado que el lenguaje de programación que uso es Java, tengo mucha exposición al proyecto Java SpringBoot, por lo que me preocupa más cómo compilar mejor las imágenes de Docker a través de Dockerfile.

        En pocas palabras, los microservicios de Kubernetes son la disposición, combinación y ajuste mutuo de un grupo de imágenes. Por lo tanto, la forma de compilar las imágenes mejorará el rendimiento del servicio, acelerará la construcción, la inserción y la extracción de imágenes y hará que ocupe menos recursos de red. Aquí optimizar y facilitar su uso se ha convertido en una máxima prioridad, y también es un tema que vale la pena considerar. Aquí describiré brevemente cómo escribir un Dockerfile para empaquetar la imagen de Docker del proyecto SpringBoot.

Entorno del sistema:


1. Explore cómo Springboot compila imágenes de Docker con regularidad

        Aquí usaremos SpringBoot normal para compilar el Dockerfile de la imagen de Docker y sentiremos cómo funciona la imagen compilada de esta manera.

1. Prepare el proyecto SpringBoot para compilar la imagen.

        Aquí preparamos un proyecto springboot ordinario compilado por Maven para construir la imagen de Docker. El contenido del proyecto es como se muestra en la figura siguiente. Puede ver que lo que se utiliza es el archivo Jar de la aplicación interna, que se almacena en la imagen para completar la construcción de la imagen Tarea.

  • Tamaño del archivo jar: 70,86 MB

2. Prepare el archivo Docker

        La creación de una imagen de Docker requiere la preparación previa de un archivo Dockerfile. El contenido de este archivo Dockerfile son las instrucciones que se ejecutarán para crear la imagen de Docker. El siguiente es un Dockerfile de uso común para crear imágenes de Docker con SpringBoot. Colóquelo en el directorio de origen de Java (el directorio de nivel superior del destino) y asegúrese de que la ruta establecida en el script de Dockerfile establecido a continuación corresponda con la ruta de destino.

FROM openjdk:8u212-b04-jre-slim
VOLUME /tmp
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]

3. Cree una imagen de Docker

        Cree la imagen de Docker mediante el comando de compilación de Docker y observe el tiempo de compilación.

Dado que la imagen debe enviarse al almacén de Aliyun Docker más adelante, el prefijo de la imagen es Aliyun.

  • tiempo: Este parámetro mostrará el tiempo transcurrido del proceso de ejecución
$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .

Proceso de construcción

Sending build context to Docker daemon  148.7MB
Step 1/7 : FROM openjdk:8u212-b04-jre-slim
8u212-b04-jre-slim: Pulling from library/openjdk
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456c
Status: Downloaded newer image for openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/7 : VOLUME /tmp
 ---> Running in 13a67ab65d2b
Removing intermediate container 13a67ab65d2b
 ---> 52011f49ddef
Step 3/7 : ADD target/*.jar app.jar
 ---> 26aa41a404fd
Step 4/7 : RUN sh -c 'touch /app.jar'
 ---> Running in 722e7e44e04d
Removing intermediate container 722e7e44e04d
 ---> 7baedb10ec62
Step 5/7 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in 2681d0c5edac
Removing intermediate container 2681d0c5edac
 ---> 5ef4a794b992
Step 6/7 : ENV APP_OPTS=""
 ---> Running in 5c8924a2a49d
Removing intermediate container 5c8924a2a49d
 ---> fba87c19053a
Step 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in c4cf97009b3c
Removing intermediate container c4cf97009b3c
 ---> d5f30cdfeb81
Successfully built d5f30cdfeb81
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m13.778s
user	0m0.078s
sys	0m0.153s

Vi que esta compilación se completó en 14 segundos .

4. Envíe la imagen al almacén de imágenes.

Envíe la imagen al almacén de Aliyun, luego verifique y registre el tiempo de envío

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

Proceso de implementación

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
cc1a2376d7c0: Pushed 
2b940d07e9e7: Pushed 
9544e87fb8dc: Pushed 
feb5d0e1e192: Pushed 
8fd22162ddab: Pushed 
6270adb5794c: Pushed 
0.0.1: digest: sha256:dc60d304383b1441941ca4e9abc08db775d7be57ccb7c534c929b34ff064a62f size: 1583

real	0m24.335s
user	0m0.052s
sys	0m0.059s

Esta vez lo vi completado en 25 segundos .

5. Tira de la imagen

Aquí, cambie a otro servidor para realizar la operación de extracción de imágenes y observe el tiempo de extracción de imágenes.

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

proceso de extracción

0.0.1: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
4847672cbfa5: Pull complete 
b60476972fc4: Pull complete 
Digest: sha256:dc60d304383b1441941ca4e9abc08db775d7be57ccb7c534c929b34ff064a62f
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m27.528s
user	0m0.033s
sys	0m0.192s

Se puede ver que este tirón tardó un total de 28 segundos en completarse.

6. Modifique el código fuente de Java, vuelva a empaquetar el Jar y vuelva a intentarlo.

        Aquí, se modifica el contenido del archivo JAVA del código fuente y luego se vuelve a empaquetar el paquete Jar, de modo que se intenten nuevamente los procesos de compilación, inserción y extracción. Dado que Docker utiliza el almacenamiento en caché jerárquico al ejecutar la compilación, este es un proceso más rápido.

(1), compilar

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .

Sending build context to Docker daemon  148.7MB
Step 1/7 : FROM openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/7 : VOLUME /tmp
 ---> Using cache
 ---> 52011f49ddef
Step 3/7 : ADD target/*.jar app.jar
 ---> c67160dd2a23
Step 4/7 : RUN sh -c 'touch /app.jar'
 ---> Running in 474900d843a2
Removing intermediate container 474900d843a2
 ---> 3ce9a8bb2600
Step 5/7 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in f48620b1ad36
Removing intermediate container f48620b1ad36
 ---> 0478f8f14e5b
Step 6/7 : ENV APP_OPTS=""
 ---> Running in 98485fb15fc8
Removing intermediate container 98485fb15fc8
 ---> 0b567c848027
Step 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in e32242fc6efe
Removing intermediate container e32242fc6efe
 ---> 7b223b23ebfd
Successfully built 7b223b23ebfd
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m3.190s
user	0m0.039s
sys	0m0.403s

        Puede ver que en el proceso de compilación de la imagen, las primeras 1 y 2 capas se almacenan en caché, por lo que la velocidad es muy rápida. El proceso de compilación total tarda menos de 4 segundos en completarse.

(2), empujar

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
d66a2fec30b5: Pushed 
f4da2c7581aa: Pushed 
9544e87fb8dc: Layer already exists 
feb5d0e1e192: Layer already exists 
8fd22162ddab: Layer already exists 
6270adb5794c: Layer already exists 

real	0m20.816s
user	0m0.024s
sys	0m0.081s

        Puede ver que solo se envían las dos primeras capas y las otras cuatro capas no se envían porque el almacén remoto no ha cambiado. Todo el proceso de inserción tarda 21 segundos en completarse.

(3), tirar

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

0.0.2: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Already exists 
04305660f45e: Already exists 
bbe7020b5561: Already exists 
d7e364f0d94a: Pull complete 
8d688ada35b1: Pull complete 
Digest: sha256:7c13c40fa92ec2fdc3a8dfdd3232be1be9c1a1a99bf123743ff2a43907ee03dc
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m23.214s
user	0m0.053s
sys	0m0.097s

        Las primeras cuatro capas se almacenan en caché localmente y solo se extraen las dos últimas capas con cambios. Este proceso tarda 24 segundos en completarse.

7. Sentimientos durante el uso del mirroring

        Al crear una imagen de Docker para el proyecto SpringBoot de esta manera, creo que siempre que haya un ligero cambio en el código fuente, el proyecto SpringBoot necesita compilar el proyecto a través de Maven y luego construir la imagen de Docker, cada vez que 70M+ Cuando el archivo Jar de la aplicación se almacena en Docker, a veces, incluso si se cambia una letra, es posible que sea necesario guardar todo el programa Jar en la imagen de Docker nuevamente y, durante el proceso de inserción y extracción, se debe insertar una imagen grande o una imagen. cada vez. Extraer una imagen grande para transferirla parece muy inconveniente.

2. Comprender el mecanismo de almacenamiento en caché y capas de Docker

1. Introducción al almacenamiento en caché jerárquico de Docker

        Para ahorrar espacio de almacenamiento, Docker adopta el concepto de almacenamiento en capas. Diferentes imágenes pueden compartir el acceso a la imagen básica. Para obtener información sobre capas de imágenes, puede visitar la capa de imágenes en la documentación oficial de Docker. Hay una introducción detallada a los temas relevantes. documentos La dirección es la siguiente:

        Documentación oficial del caché de imágenes de Docker: https://docs.docker.com/storage/storagedriver/

        Durante el proceso de creación de la imagen, Docker ejecutará gradualmente las instrucciones en el Dockerfile en el orden especificado en el Dockerfile. A medida que se verifica cada instrucción, Docker buscará en su caché una imagen existente que pueda reutilizarse, en lugar de crear una imagen nueva (duplicada).

        Cada línea de comando en Dockerfile crea una nueva capa, incluidos los cambios en el sistema de archivos antes y después de la ejecución de esta línea de comando.

        Para optimizar este proceso, Docker utiliza un mecanismo de almacenamiento en caché: mientras esta línea de comando permanezca sin cambios, el resultado será el mismo que la última vez y el último resultado se puede usar directamente.

        Para aprovechar al máximo el almacenamiento en caché jerárquico, debemos comprender cómo funciona la línea de comandos en Dockerfile, especialmente los comandos RUN, ADD y COPY.

2. Capas de la imagen SpringBoot Docker

        Después de compilar SpringBoot en una imagen, la capa inferior será un sistema, como Ubantu, la capa superior es la capa JDK dependiente y luego la capa SpringBoot. Las dos capas inferiores dependen de la imagen básica y no hay mucho espacio para la optimización, por lo que al optimizar la imagen, consideramos más sobre cómo optimizar la capa SpringBoot y reflexionamos sobre esta capa.

3. ¿Qué causa que Jar se hinche?

        Del experimento anterior, aprendimos que la razón por la cual cada proceso de compilación, inserción y extracción es relativamente lento es el enorme archivo de imagen. Después de comprender el concepto de almacenamiento en caché de Docker, se me ocurrió la idea de que si los archivos que no cambian con frecuencia se almacenan en caché, los archivos que se cambian con frecuencia no se almacenarán en caché. Dado que los proyectos SpringBoot cambian con frecuencia, ¿cómo deberíamos utilizar el mecanismo de almacenamiento en caché para implementarlo? Si el caché se usa a la fuerza, ¿no sería la imagen tomada cada vez el contenido del programa antiguo en el caché?

        Entonces, considere qué archivos están incluidos en el paquete Jar de la aplicación, qué archivos Java se cambian con frecuencia y cuáles no se cambian con frecuencia. En este sentido, a continuación se analizará el paquete Jar de la aplicación creado por SpringBoot.

1. Descomprima el paquete Jar y vea el contenido.

Mostrar la lista descomprimida y ver el tamaño de cada carpeta

$ tree -L 3 --si --du

.
├── [ 74M]  BOOT-INF 
│   ├── [2.1k]  classes
│   └── [ 74M]  lib
├── [ 649]  META-INF
│   ├── [ 552]  MANIFEST.MF
│   └── [  59]  maven
└── [  67]  org
    └── [  38]  springframework

        Puede ver que el archivo más grande es la carpeta lib. Cuando abre esta carpeta, hay un montón de Jars dependientes relacionados. Uno de los Jars no es grande, pero un montón de Jars combinados serán muy grandes. Generalmente, proyectos SpringBoot Depende del tamaño del tarro. Mantener entre 40 MB y 160 MB.

        Si observa la carpeta de organización, el código total que contiene es de solo unos pocos cientos de KB. Por lo tanto, el paquete Jar del programa SpringBoot se compone de estos archivos de Clases y Jar dependientes. Estos Jar dependientes suman un total de 74 MB, lo que representa casi el tamaño completo del paquete Jar de la aplicación.

2. Nuevas ideas para solucionar la hinchazón

        Si un paquete Jar solo contiene archivos de clase, el tamaño del paquete Jar puede ser de varios cientos de KB. Ahora queremos explorar, si separamos el Jar y la clase de la que depende la biblioteca, configuramos el paquete Jar de la aplicación para que solo contenga archivos de clase y colocamos los archivos Jar en la carpeta lib fuera del SpringBoot Jar.

        Cuando escribimos un programa, el Jar en el que a menudo se basa no cambia con frecuencia. Lo que más cambia es el código fuente del programa. El paquete Jar en el que se basa es muy grande y el código fuente es muy pequeño. Piénselo detenidamente, si configura una capa de caché separada para el paquete Jar del que depende la aplicación cuando la empaqueta en una imagen de Docker, y el paquete Jar de la aplicación solo contiene archivos Class, entonces durante la compilación, empuje y extraiga procesos de Docker, excepto por primera vez Además de ejecutar todo, en los procesos posteriores de compilación, inserción y extracción, solo se operará el archivo Jar modificado que contiene solo Clase, que es solo unos pocos cientos de KB. que este proceso se pueda completar al instante. Así que piense en cómo separar el paquete Jar dependiente y el paquete Jar de la aplicación en la carpeta lib.

3. Cómo solucionar la separación de archivos lib y class

        Después de buscar mucha información relevante, descubrí que el complemento Maven de SpringBoot hace muchas cosas al ejecutar Maven para compilar y construir paquetes Jar. Si cambia la lógica de empaquetado de algunos complementos, puede agregar las dependencias de la aplicación a la carpeta lib al crear el paquete Jar de la aplicación . Todos los Jar se copian fuera del Jar de la aplicación, dejando solo los archivos de clase de código de bytes compilados .

        Después de muchas búsquedas en Internet, encontré un método de implementación, el siguiente: introduzca estas herramientas Maven en el proyecto pom.xml

<build>
    <plugins>
        <!--设置应用 Main 参数启动依赖查找的地址指向外部 lib 文件夹-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <!--设置 SpringBoot 打包插件不包含任何 Jar 依赖包-->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                 <includes>
                     <include>
                         <groupId>nothing</groupId>
                         <artifactId>nothing</artifactId>
                     </include>
                 </includes>
            </configuration>
        </plugin>
        <!--设置将 lib 拷贝到应用 Jar 外面-->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Ejecute el comando Maven para empaquetar Jar

$ mvn clean install

Después de ejecutar el comando Maven, vea el directorio de destino como se muestra a continuación:

        Puede ver que el jar de la aplicación se ha vuelto muy pequeño y la carpeta lib se ha colocado fuera del jar. El paquete jar ya no está integrado, sino que la dirección lib se especifica cuando se ejecuta el jar de la aplicación para que se pueda cargar. .

        Pase lo que pase, debemos probar si este archivo Jar se puede ejecutar normalmente. Sólo la ejecución normal puede demostrar que esta solución es factible.

Ejecute el siguiente comando para probar si el jar puede iniciarse normalmente:

$ java -jar springboot-helloworld-0.0.1.jar

        Puedo ver el registro de ejecución durante la operación y muestra que la operación fue exitosa, lo que significa que esta solución es factible. Sin embargo, nuestro trabajo de transformación aún no ha terminado y continuaremos con el trabajo de transformación de Dockerfile.

4. Hablemos de cómo transformar Springboot y compilar imágenes de Docker.

Dirección del proyecto Github: https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-dockerfile

1. Modifique el archivo Dockerfile

        Para modificar el Dockerfile anterior, debe agregar la siguiente instrucción:

COPY target/lib/ ./lib/

        Este comando se usa para copiar el Jar dependiente en el directorio lib a la imagen. El resto permanece consistente con el Dockerfile anterior .

FROM openjdk:8u212-b04-jre-slim
VOLUME /tmp
COPY target/lib/ ./lib/
ADD target/*.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]

Aquí se agrega una nueva capa de instrucciones, que se utiliza para copiar la carpeta lib a la imagen. Debido al mecanismo de almacenamiento en caché de Docker, esta capa debe estar antes de copiar el Jar de la aplicación. De esta manera, después de la transformación, cada vez que el dependiente Jar en la carpeta lib no está Si se cambia la capa, no se creará una nueva capa, pero se reutilizará el caché.

2. Primera compilación, inserción y extracción después de transformar la imagen de Docker

        Aquí comenzamos a intentar realizar compilación, push y pull para probar su velocidad. Antes de la ejecución, primero limpiamos todos los recursos relacionados con la última imagen del servidor para reducir el impacto en el entorno de prueba.

(1) Prueba y registro de velocidad de compilación

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .

Sending build context to Docker daemon  223.2MB
Step 1/8 : FROM openjdk:8u212-b04-jre-slim
8u212-b04-jre-slim: Pulling from library/openjdk
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456c
Status: Downloaded newer image for openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/8 : VOLUME /tmp
 ---> Running in 529369acab24
Removing intermediate container 529369acab24
 ---> ad689d937118
Step 3/8 : COPY target/lib/ ./lib/
 ---> 029a64c15853
Step 4/8 : ADD target/*.jar app.jar
 ---> 6265a83a1b90
Step 5/8 : RUN sh -c 'touch /app.jar'
 ---> Running in 839032a58e6b
Removing intermediate container 839032a58e6b
 ---> 5d877dc35b2b
Step 6/8 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in 4043994c5fed
Removing intermediate container 4043994c5fed
 ---> 7cf32beb571f
Step 7/8 : ENV APP_OPTS=""
 ---> Running in b7dcfa10458a
Removing intermediate container b7dcfa10458a
 ---> b6b332bcf0e6
Step 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in 539093461b59
Removing intermediate container 539093461b59
 ---> d4c095c4ffec
Successfully built d4c095c4ffec
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m22.983s
user	0m0.051s
sys	0m0.540s

(2) Prueba y registro de velocidad de empuje

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
c16749205e05: Pushed 
7fef1a146748: Pushed 
a3bae74bbdf2: Pushed 
9544e87fb8dc: Pushed
feb5d0e1e192: Pushed
8fd22162ddab: Pushed
6270adb5794c: Pushed 
0.0.1: digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157 size: 1789

real	0m30.335s
user	0m0.052s
sys	0m0.059s

(3) Prueba y registro de velocidad de tracción

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

0.0.1: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Pull complete 
04305660f45e: Pull complete 
bbe7020b5561: Pull complete 
de6c4f15d75b: Pull complete 
7066947b7d89: Pull complete 
e0742de67c75: Pull complete 
Digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1

real	0m36.585s
user	0m0.024s
sys	0m0.092s

3. Compile, presione y extraiga nuevamente

        Ejecutamos la compilación de la imagen nuevamente para probar Step 3/8 : COPY target/lib/ ./lib/si la imagen en el caché se reutiliza cuando se completa la compilación.

(1) Prueba y registro de velocidad de compilación

$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .

Sending build context to Docker daemon  223.2MB
Step 1/8 : FROM openjdk:8u212-b04-jre-slim
 ---> 7c6b62cf60ee
Step 2/8 : VOLUME /tmp
 ---> Using cache
 ---> ad689d937118
Step 3/8 : COPY target/lib/ ./lib/
 ---> Using cache
 ---> 029a64c15853
Step 4/8 : ADD target/*.jar app.jar
 ---> 563773953844
Step 5/8 : RUN sh -c 'touch /app.jar'
 ---> Running in 3b9df57802bd
Removing intermediate container 3b9df57802bd
 ---> 706a0d47317f
Step 6/8 : ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
 ---> Running in defda61452bf
Removing intermediate container defda61452bf
 ---> 742c7c926374
Step 7/8 : ENV APP_OPTS=""
 ---> Running in f09b81d054dd
Removing intermediate container f09b81d054dd
 ---> 929ed5f8b12a
Step 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
 ---> Running in 5dc66a8fc1e6
Removing intermediate container 5dc66a8fc1e6
 ---> c4942b10992c
Successfully built c4942b10992c
Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m2.524s
user	0m0.051s
sys	0m0.493s

Como puede ver, esta vez todo el proceso de compilación solo tomó 2,5 segundos para el caché utilizado directamente en la capa 3.

(2) Prueba y registro de velocidad de empuje

$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]
d719b9540809: Pushed 
d45bf4c5fb92: Pushed 
a3bae74bbdf2: Layer already exists 
9544e87fb8dc: Layer already exists 
feb5d0e1e192: Layer already exists 
8fd22162ddab: Layer already exists 
6270adb5794c: Layer already exists 
0.0.2: digest: sha256:b46d81b153ec64321caaae7ab28da0e362ed7d720a7f0775ea8d1f7bef310d00 size: 1789

real	0m0.168s
user	0m0.016s
sys	0m0.032s

Puede ver que el envío de la imagen se completó en 0,2 segundos .

(3) Prueba y registro de velocidad de tracción

$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

0.0.2: Pulling from mydlq/springboot
743f2d6c1f65: Already exists 
b83e581826a6: Already exists 
04305660f45e: Already exists 
bbe7020b5561: Already exists 
de6c4f15d75b: Already exists 
1c77cc70cc41: Pull complete 
aa5b8cbca568: Pull complete 
Digest: sha256:b46d81b153ec64321caaae7ab28da0e362ed7d720a7f0775ea8d1f7bef310d00
Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2

real	0m1.947s
user	0m0.017s
sys	0m0.042s

Puede ver que la extracción de la imagen se completó en 2 segundos .

5. Resumen final

        Debido a las fluctuaciones de la red y los cambios del sistema, el tiempo solo se puede usar como referencia, pero los procesos de compilación, inserción y extracción son mucho más rápidos. La mayoría de los archivos se almacenan en caché y la interacción de tráfico de solo unos pocos cientos de KB es naturalmente, más rápido que decenas de MB o incluso cientos de MB son mucho más rápidos.

        Finalmente, permítanme explicarles que este enfoque solo proporciona una referencia. Dado que Docker refleja actualmente los servicios de microservicio, la imagen completa se mantiene en lugar de un programa de servicio, por lo que la preocupación es si la imagen de Docker se puede ejecutar normalmente y cómo construir la imagen. Hará que la imagen creada sea más utilizable.

        En el entorno de producción, debido a que la versión cambia lentamente y no se actualizará cada vez, es mejor seguir el método de compilación de imágenes SpringBoot original en el entorno de producción para garantizar la instalación (a menos que el método de construcción haya sido verificado por un gran número). de ejemplos).

Supongo que te gusta

Origin blog.csdn.net/yangyangye/article/details/132623528
Recomendado
Clasificación