Prática de ajuste de imagem Docker de construção de projeto Java SpringBoot

        Eu vi este documento online e achei muito bom. Reimprimi-o aqui principalmente para aprender as ideias de uso de cache hierárquico e processamento de tamanho de imagem neste artigo.

Reimpresso de: Prática de ajuste de imagem Docker de construção de projeto Java SpringBoot | Xiaodudin Technology Stack

PS: Foi verificado na prática de produção para resolver o problema que no ambiente de produção a velocidade da rede e a largura de banda são pequenas e cada push e pull da imagem afeta o serviço online. A imagem é construída de acordo com o método neste artigo. Além de puxar, empurrar e construir lentamente a imagem pela primeira vez, a segunda, a segunda, a terceira... vezes tinham centenas de K em tamanho. A velocidade foi muito rápida, e a construção, embalagem, e push foram concluídos em alguns segundos.

Prefácio:

        Na era anterior dos microsserviços Spring Cloud, os "pacotes Jar" eram a base dos serviços. Cada serviço era empacotado em um Jar para inter-relacionamento e chamadas entre serviços. Agora, com a popularidade do Kubernetes, ele mudou para uma imagem e um serviço, e o Kubernetes depende da orquestração unificada de imagens para gerenciar serviços de maneira uniforme. No processo de prática de microsserviços Kubernetes, o mais exposto é definitivamente a imagem Docker. Como a linguagem de programação que uso é Java, tenho muito contato com o projeto Java SpringBoot, por isso estou mais preocupado em como compilar melhor as imagens do Docker por meio do Dockerfile.

        Simplificando, os microsserviços Kubernetes são o arranjo, combinação e ajuste mútuo de um grupo de imagens.Portanto, a forma de compilar as imagens melhorará o desempenho do serviço, tornará a construção da imagem, push e pull mais rápida e fará com que ela ocupe menos recursos de rede Aqui, otimizar e facilitar o uso tornou-se uma prioridade máxima e também é uma questão que vale a pena considerar. Aqui descreverei brevemente como escrever um Dockerfile para empacotar a imagem Docker do projeto SpringBoot.

Ambiente do sistema:


1. Explore como o Springboot normal compila imagens Docker

        Aqui usaremos SpringBoot regular para compilar o Dockerfile da imagem Docker e sentir como funciona a imagem compilada dessa forma.

1. Prepare o projeto SpringBoot para compilar a imagem

        Aqui preparamos um projeto springboot comum compilado pelo Maven para construir a imagem Docker. O conteúdo do projeto é mostrado na figura abaixo. Você pode ver que o que é usado é o arquivo Jar do aplicativo dentro, que está armazenado na imagem para completar a construção da imagem. Tarefa.

  • tamanho do arquivo jar: 70,86 MB

2. Prepare o Dockerfile

        Construir uma imagem Docker requer a preparação antecipada de um arquivo Dockerfile. O conteúdo deste arquivo Dockerfile são as instruções a serem executadas para construir a imagem Docker. A seguir está um Dockerfile comumente usado para construir imagens Docker com SpringBoot. Coloque-o no diretório de origem Java (o diretório de nível superior do destino) e certifique-se de que o caminho definido no script Dockerfile definido abaixo corresponda ao caminho 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. Construir imagem Docker

        Construa a imagem do Docker por meio do comando Docker build e observe o tempo de compilação.

Como a imagem precisa ser enviada posteriormente para o armazém Aliyun Docker, o prefixo da imagem é Aliyun.

  • time: Este parâmetro exibirá o tempo decorrido do processo de execução
$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .

Processo de construção

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 compilação foi concluída em 14 segundos .

4. Envie a imagem para o armazém de imagens

Envie a imagem para o armazém Aliyun e, em seguida, verifique e registre o tempo de envio

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

Processo de implementação

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

Vi -o concluído em 25 segundos desta vez .

5. Puxe a imagem

Aqui, mude para outro servidor para realizar a operação de extração de imagem e observe o tempo de extração de imagem.

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

Processo de puxar

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

Pode-se observar que essa puxada levou um total de 28 segundos para ser concluída.

6. Modifique o código-fonte Java, empacote novamente o Jar e tente novamente

        Aqui, o conteúdo do arquivo JAVA do código-fonte é modificado e, em seguida, o pacote Jar é reembalado, para que os processos de compilação, push e pull sejam tentados novamente. Como o Docker usa cache hierárquico ao executar a construção, este é um processo mais 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

        Você pode ver que no processo de compilação da imagem, as primeiras 1 e 2 camadas são armazenadas em cache, então a velocidade é muito rápida. O processo total de compilação leva menos de 4 segundos para ser concluído.

(2), empurre

$ 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

        Você pode ver que apenas as duas primeiras camadas são enviadas e as outras quatro camadas não são enviadas porque o armazém remoto não foi alterado. Todo o processo push leva 21 segundos para ser concluído.

(3), puxe

$ 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

        As primeiras quatro camadas são armazenadas em cache localmente e apenas as duas últimas camadas com alterações são extraídas. Este processo leva 24 segundos para ser concluído.

7. Sentimentos durante o uso do espelhamento

        Ao construir uma imagem Docker para o projeto SpringBoot dessa forma, minha sensação é que, desde que haja uma ligeira alteração no código-fonte, o projeto SpringBoot precisa compilar o projeto por meio do Maven e, em seguida, construir a imagem Docker, cada vez que um 70M+ Quando o arquivo Jar do aplicativo é armazenado no Docker, às vezes, mesmo que uma letra seja alterada, todo o programa Jar pode ter que ser salvo na imagem do Docker novamente. Então, durante o processo de push e pull, uma imagem grande ou imagem deve ser enviada a cada vez. Extrair uma imagem grande para transferência parece muito inconveniente.

2. Compreenda as camadas do Docker e o mecanismo de cache

1. Introdução ao cache hierárquico do Docker

        Para economizar espaço de armazenamento, o Docker adota o conceito de armazenamento em camadas. Imagens diferentes podem compartilhar o acesso à imagem básica. Para obter informações sobre camadas de imagens, você pode visitar a camada de imagens na documentação oficial do Docker. Há uma introdução detalhada ao relevante documentos. O endereço é o seguinte:

        Documentação oficial do cache de imagem Docker: https://docs.docker.com/storage/storagedriver/

        Durante o processo de construção da imagem, o Docker executará gradualmente as instruções do Dockerfile na ordem especificada no Dockerfile. À medida que cada instrução é verificada, o Docker procurará em seu cache uma imagem existente que possa ser reutilizada, em vez de criar uma nova imagem (duplicada).

        Cada linha de comando no Dockerfile cria uma nova camada, incluindo as alterações no sistema de arquivos antes e depois da execução desta linha de comando.

        Para otimizar este processo, o Docker utiliza um mecanismo de cache: enquanto esta linha de comando permanecer inalterada, o resultado será o mesmo da última vez, e o último resultado pode ser usado diretamente.

        Para aproveitar ao máximo o cache hierárquico, devemos entender como funciona a linha de comando no Dockerfile, especialmente os comandos RUN, ADD e COPY.

2. Camadas de imagem SpringBoot Docker

        Depois que o SpringBoot for compilado em uma imagem, a camada inferior será um sistema, como Ubantu, a camada superior será a camada JDK dependente e, em seguida, a camada SpringBoot. As duas camadas inferiores dependem da imagem básica e não há muito espaço para otimização, portanto, ao otimizar a imagem, consideramos mais sobre como otimizar a camada SpringBoot e ponderamos sobre essa camada.

3. O que faz com que Jar fique inchado?

        Com o experimento acima, aprendemos que a razão pela qual cada processo de compilação, push e pull é relativamente lento é o enorme arquivo de imagem. Depois de entender o conceito de cache do Docker, tive a ideia de que se os arquivos que não mudam com frequência forem armazenados em cache, os arquivos que são alterados com frequência não serão armazenados em cache. Como os projetos SpringBoot mudam com frequência, como devemos usar o mecanismo de cache para implementá-los? Se o cache for usado à força, a imagem obtida todas as vezes não seria o conteúdo antigo do programa no cache?

        Portanto, considere quais arquivos estão incluídos no pacote Jar do aplicativo, quais arquivos Java são alterados com frequência e quais não são alterados com frequência. A esse respeito, analisaremos a seguir o pacote Jar do aplicativo criado pelo SpringBoot.

1. Descompacte o pacote Jar e visualize o conteúdo

Exiba a lista descompactada e veja o tamanho de cada pasta

$ 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

        Você pode ver que o maior arquivo é a pasta lib. Quando você abre esta pasta, há vários Jars de dependência relacionados. Um dos Jars não é grande, mas um monte de Jars combinados será muito grande. Geralmente, projetos SpringBoot depende do tamanho do frasco. Mantenha entre 40 MB e 160 MB.

        Olhando para a pasta org, o código total dentro dela é de apenas algumas centenas de KB. Portanto, o pacote Jar do programa SpringBoot é composto por esses arquivos de Classes e Jars dependentes.Esses Jars dependentes totalizam 74 MB, representando quase todo o tamanho do pacote Jar do aplicativo.

2. Novas ideias para resolver o inchaço

        Se um pacote Jar contiver apenas arquivos de classe, o tamanho do pacote Jar poderá ser de várias centenas de KB. Agora queremos explorar, se separarmos o Jar e a classe da qual a lib depende, definirmos o pacote Jar do aplicativo para conter apenas arquivos de classe e colocarmos os arquivos Jar na pasta lib fora do SpringBoot Jar.

        Quando escrevemos um programa, o Jar do qual ele depende frequentemente não muda com frequência. O que mais muda é o código-fonte do programa. O pacote Jar do qual ele depende é muito grande e o código-fonte é muito pequeno. Pense nisso com cuidado, se você configurar uma camada separada de cache para o pacote Jar da qual o aplicativo depende ao empacotá-lo em uma imagem Docker, e o pacote Jar do aplicativo contém apenas arquivos de classe, durante a compilação, push e pull processos do Docker, exceto pela primeira vez Além de executar tudo, nos processos subseqüentes de compilação, push e pull, apenas o arquivo Jar alterado contendo apenas Classe será operado, o que tem apenas algumas centenas de KB. Pode-se dizer que este processo pode ser concluído instantaneamente. Então pense em como separar o pacote Jar dependente e o pacote Jar do aplicativo na pasta lib.

3. Como resolver a separação de arquivos lib e class

        Depois de pesquisar muitas informações relevantes, descobri que o plug-in Maven do SpringBoot faz muitas coisas ao executar o Maven para compilar e construir pacotes Jar. Se você alterar a lógica de empacotamento de alguns plug-ins, poderá adicionar as dependências do aplicativo a a pasta lib ao construir o pacote Jar do aplicativo . Todos os Jars são copiados fora do Jar do aplicativo, deixando apenas os arquivos de classe de bytecode compilados .

        Depois de muitas pesquisas na Internet, encontrei um método de implementação, como segue, introduza essas ferramentas Maven no projeto 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>

Execute o comando Maven para empacotar Jar

$ mvn clean install

Após a execução do comando Maven, visualize o diretório de destino conforme mostrado abaixo:

        Você pode ver que o jar do aplicativo ficou muito pequeno e a pasta lib foi colocada fora do jar. O pacote jar não está mais integrado. Em vez disso, o endereço lib é especificado quando o jar do aplicativo está em execução para que possa ser carregado .

        Não importa o que aconteça, precisamos testar se este arquivo Jar pode ser executado normalmente. Somente a execução normal pode provar que esta solução é viável.

Execute o seguinte comando para testar se o jar pode iniciar normalmente:

$ java -jar springboot-helloworld-0.0.1.jar

        Posso ver o log de execução durante a operação e mostra que a operação foi bem-sucedida, o que significa que esta solução é viável. No entanto, nosso trabalho de transformação ainda não terminou e continuaremos o trabalho de transformação do Dockerfile.

4. Vamos falar sobre como transformar Springboot e compilar imagens Docker

Endereço do projeto Github: https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-dockerfile

1. Modifique o arquivo Dockerfile

        Para modificar o Dockerfile acima, você precisa adicionar a seguinte instrução:

COPY target/lib/ ./lib/

        Este comando é usado para copiar o Jar dependente do diretório lib para a imagem. O restante permanece consistente com o Dockerfile acima .

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" ]

Uma nova camada de instruções é adicionada aqui, que é usada para copiar a pasta lib para a imagem. Devido ao mecanismo de cache do Docker, esta camada deve ser antes de copiar o Jar da aplicação. Desta forma, após a transformação, toda vez que o dependente Jar na pasta lib não é Se a camada for alterada, uma nova camada não será criada, mas o cache será reutilizado.

2. Primeira compilação, push e pull após transformar a imagem Docker

        Aqui começamos a realmente tentar realizar compilação, push e pull para testar sua velocidade.Antes da execução, primeiro limpamos todos os recursos relacionados à última imagem do servidor para reduzir o impacto no ambiente de teste.

(1) Teste e registro de velocidade de compilação

$ 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) Teste de velocidade de impulso e registro

$ 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) Teste de velocidade de tração e registro

$ 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. Compilar, enviar e extrair novamente

        Executamos a construção da imagem novamente para testar Step 3/8 : COPY target/lib/ ./lib/se a imagem no cache será reutilizada quando a construção for concluída.

(1) Teste e registro de velocidade de compilação

$ 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 você pode ver, desta vez todo o processo de compilação levou apenas 2,5 segundos para o cache usado diretamente na camada 3.

(2) Teste de velocidade de impulso e registro

$ 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

Você pode ver que o envio da imagem foi concluído em 0,2s .

(3) Teste de velocidade de tração e registro

$ 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

Você pode ver que a extração da imagem foi concluída em 2 segundos .

5. Resumo final

        Devido às flutuações da rede e mudanças no sistema, o tempo só pode ser usado como referência, mas os processos de compilação, push e pull são realmente muito mais rápidos. A maioria dos arquivos é armazenada em cache e a interação de tráfego de apenas algumas centenas de KB é naturalmente mais rápido do que dezenas de MB ou mesmo centenas de MB são muito mais rápidos.

        Por fim, deixe-me explicar que esta abordagem fornece apenas uma referência. Como o atual espelhamento do Docker de serviços de microsserviços, a imagem inteira é mantida em vez de um programa de serviço, então a preocupação é se a imagem do Docker pode ser executada normalmente e como construir a imagem Isso tornará a imagem construída mais utilizável.

        No ambiente de produção, como a versão muda lentamente e não será atualizada a cada passo, é melhor seguir o método de compilação de imagem SpringBoot original no ambiente de produção para garantir a instalação (a menos que o método de construção tenha sido verificado por um grande número de exemplos).

Acho que você gosta

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