02.28 SpringBoot 項目構建 Docker 鏡像調優實踐

http://www.mydlq.club/article/16/

PS:已經在生產實踐中驗證,解決在生產環境下,網速帶寬小,每次推拉鏡像影響線上服務問題,按本文方式構建鏡像,除了第一次拉取、推送、構建鏡像慢,第二、三…次都是幾百K大小傳輸,速度非常快,構建、打包、推送幾秒內完成。

前言:

以前的 SpringCloud 微服務時代以 “Jar包” 為服務的基礎,每個服務都打成 Jar 供服務間相互關聯與調用。而 現在隨著 Kubernetes 流行,已經變遷到一個鏡像一個服務,依靠 Kubernetes 對鏡像的統一編排進行對服務進行統一管理。在對 Kubernetes 微服務實踐過程中,接觸最多的肯定莫過於 Docker 鏡像。由於本人使用的編程語言是 Java,所以對 Java SpringBoot 項目接觸比較多,所以比較關心如何更好的通過 Dockerfile 編譯 Docker 的鏡像。

Kubernetes 微服務簡單說就是一群鏡像間的排列組合與相互間調的關係,故而如何編譯鏡像會使服務性能更優,使鏡像構建、推送、拉取速度更快,使其佔用網絡資源更少這裡優化,更易使用成為了一個重中之重的事情,也是一個非常值得琢磨的問題。

這裡我將對 SpringBoot 項目打包 Docker 鏡像如何寫 Dockerfile 的探究進行簡單敘述。

系統環境:

Docker 版本:18.09.3

Open JDK 基礎鏡像版本:openjdk:8u212-b04-jre-slim

測試用的鏡像倉庫:阿里雲 Docker Hub

項目 Github:https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-dockerfile

一、探究常規 Springboot 如何編譯 Docker 鏡像

這裡將用常規 SpringBoot 編譯 Docker 鏡像的 Dockerfile 寫法,感受下這種方式編譯的鏡像用起來如何。

1、準備編譯鏡像的 SpringBoot 項目

這裡準備一個經過 Maven 編譯後的普通的 springboot 項目來進行 Docker 鏡像構建,項目內容如下圖所示,可以看到要用到的就是裡面的應用程序的 Jar 文件,將其存入鏡像內完成鏡像構建任務。

jar 文件大小:70.86mb

SpringBoot 項目構建 Docker 鏡像調優實踐

2、準備 Dockerfile 文件

構建 Docker 鏡像需要提前準備 Dockerfile 文件,這個 Dockerfile 文件中的內容為構建 Docker 鏡像執行的指令。

下面是一個常用的 SpringBoot 構建 Docker 鏡像的 Dockerfile,將它放入 Java 源碼目錄(target 的上級目錄),確保下面設置的 Dockerfile 腳本中設置的路徑和 target 路徑對應。

<code>FROM openjdk:8u212-b04-jre-slimVOLUME /tmpADD target/*.jar app.jarRUN sh -c 'touch /app.jar'ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai"ENV APP_OPTS=""ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]/<code>

3、構建 Docker 鏡像

通過 Docker build 命令構建 Docker 鏡像,觀察編譯的時間。

由於後續需要將鏡像推送到 Aliyun Docker 倉庫,所以鏡像前綴用了 Aliyun。

time:此參數會顯示執行過程經過的時間

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

構建過程

<code>Sending build context to Docker daemon  148.7MBStep 1/7 : FROM openjdk:8u212-b04-jre-slim8u212-b04-jre-slim: Pulling from library/openjdk743f2d6c1f65: Already exists b83e581826a6: Pull complete 04305660f45e: Pull complete bbe7020b5561: Pull complete Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456cStatus: Downloaded newer image for openjdk:8u212-b04-jre-slim ---> 7c6b62cf60eeStep 2/7 : VOLUME /tmp ---> Running in 13a67ab65d2bRemoving intermediate container 13a67ab65d2b ---> 52011f49ddefStep 3/7 : ADD target/*.jar app.jar ---> 26aa41a404fdStep 4/7 : RUN sh -c 'touch /app.jar' ---> Running in 722e7e44e04dRemoving intermediate container 722e7e44e04d ---> 7baedb10ec62Step 5/7 : ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ---> Running in 2681d0c5edacRemoving intermediate container 2681d0c5edac ---> 5ef4a794b992Step 6/7 : ENV APP_OPTS="" ---> Running in 5c8924a2a49dRemoving intermediate container 5c8924a2a49d ---> fba87c19053aStep 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ] ---> Running in c4cf97009b3cRemoving intermediate container c4cf97009b3c ---> d5f30cdfeb81Successfully built d5f30cdfeb81Successfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1real    0m13.778suser    0m0.078ssys 0m0.153s/<code>

看到這次編譯在 14s 內完成。

4、將鏡像推送到鏡像倉庫

將鏡像推送到 Aliyun 倉庫,然後查看並記錄推送時間

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

執行過程

<code>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: 1583real    0m24.335suser    0m0.052ssys 0m0.059s/<code>

看到這次在 25s 內完成。擴展:面試官:你簡歷中寫用過docker,能說說容器和鏡像的區別嗎?

5、拉取鏡像

這裡切換到另一臺服務器上進行鏡像拉取操作,觀察鏡像拉取時間。

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

拉取過程

<code>0.0.1: Pulling from mydlq/springboot743f2d6c1f65: Already exists b83e581826a6: Pull complete 04305660f45e: Pull complete bbe7020b5561: Pull complete 4847672cbfa5: Pull complete b60476972fc4: Pull complete Digest: sha256:dc60d304383b1441941ca4e9abc08db775d7be57ccb7c534c929b34ff064a62fStatus: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1real    0m27.528suser    0m0.033ssys 0m0.192s/<code>

看到這次拉取總共用時 28s 內完成。

6、修改 Java 源碼重新打包 Jar 後再次嘗試

這裡將源碼的 JAVA 文件內容修改,然後重新打 Jar 包,這樣再次嘗試編譯、推送、拉取過程,由於 Docker 在執行構建時會採用分層緩存,所以這是一個執行較快過程。

(1)、編譯

<code>$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .Sending build context to Docker daemon  148.7MBStep 1/7 : FROM openjdk:8u212-b04-jre-slim ---> 7c6b62cf60eeStep 2/7 : VOLUME /tmp ---> Using cache ---> 52011f49ddefStep 3/7 : ADD target/*.jar app.jar ---> c67160dd2a23Step 4/7 : RUN sh -c 'touch /app.jar' ---> Running in 474900d843a2Removing intermediate container 474900d843a2 ---> 3ce9a8bb2600Step 5/7 : ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ---> Running in f48620b1ad36Removing intermediate container f48620b1ad36 ---> 0478f8f14e5bStep 6/7 : ENV APP_OPTS="" ---> Running in 98485fb15fc8Removing intermediate container 98485fb15fc8 ---> 0b567c848027Step 7/7 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ] ---> Running in e32242fc6efeRemoving intermediate container e32242fc6efe ---> 7b223b23ebfdSuccessfully built 7b223b23ebfdSuccessfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2real    0m3.190suser    0m0.039ssys 0m0.403s/<code>

可以看到在編譯鏡像過程中,前1、2層用的緩存,所以速度非常快。總編譯過程耗時 4s 內完成。

(2)、推送

<code>$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2The 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.816suser    0m0.024ssys 0m0.081s/<code>

可以看到只推送了前兩層,其它四次由於遠程倉庫未變化,所以沒有推送。整個推送過程耗時 21s 內完成。

(3)、拉取

<code>$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.20.0.2: Pulling from mydlq/springboot743f2d6c1f65: Already exists b83e581826a6: Already exists 04305660f45e: Already exists bbe7020b5561: Already exists d7e364f0d94a: Pull complete 8d688ada35b1: Pull complete Digest: sha256:7c13c40fa92ec2fdc3a8dfdd3232be1be9c1a1a99bf123743ff2a43907ee03dcStatus: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2real    0m23.214suser    0m0.053ssys 0m0.097s/<code>

本地以及緩存前四層,只拉取有變化的後兩層。這個過程耗時 24s 內完成。

7、使用鏡像過程中的感受

通過這種方式對 SpringBoot 項目構建 Docker 鏡像來使用,給我的感受就是隻要源碼中發生一點點變化,那麼 SpringBoot 項目就需要將項目經過 Maven 編譯後再經過 Docker 鏡像構建,每次都會將一個 70M+ 的應用 Jar 文件存入 Docker 中,有時候明明就改了一個字母,可能又得把整個程序 Jar 重新存入 Docker 鏡像中,然後在推送和拉取過程中,每次都得推一個大的鏡像或者拉取一個大的鏡像來進行傳輸,感覺非常不方便。

二、瞭解 Docker 分層及緩存機制

1、Docker 分層緩存簡介

Docker 為了節約存儲空間,所以採用了分層存儲概念。共享數據會對鏡像和容器進行分層,不同鏡像可以共享相同數據,並且在鏡像上為容器分配一個 RW 層來加快容器的啟動順序。

在構建鏡像的過程中 Docker 將按照 Dockerfile 中指定的順序逐步執行 Dockerfile 中的指令。隨著每條指令的檢查,Docker 將在其緩存中查找可重用的現有鏡像,而不是創建一個新的(重複)鏡像。

Dockerfile 的每一行命令都創建新的一層,包含了這一行命令執行前後文件系統的變化。為了優化這個過程,Docker 使用了一種緩存機制:只要這一行命令不變,那麼結果和上一次是一樣的,直接使用上一次的結果即可。擴展:終於有人把 Docker 講清楚了,萬字詳解!

為了充分利用層級緩存,我們必須要理解 Dockerfile 中的命令行是如何工作的,尤其是RUN,ADD和COPY這幾個命令。

參考 Docker 文檔瞭解 Docker 鏡像緩存:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

2、SpringBoot Docker 鏡像的分層

SpringBoot 編譯成鏡像後,底層會是一個系統,如 Ubantu,上一層是依賴的 JDK 層,然後才是 SpringBoot 層,最下面兩層我們無法操作,考慮優化只能是 SpringBoot 層琢磨。

SpringBoot 項目構建 Docker 鏡像調優實踐

三、是什麼導致 Jar 包臃腫

從上面實驗中瞭解到之所以每次編譯、推送、拉取過程中較為緩慢,原因就是龐大的鏡像文件。瞭解到 Docker 緩存概念後就就產生一種想法,如果不經常改變的文件緩存起來,將常改動的文件不進行緩存。擴展:SpringBoot緩存應用實踐

由於 SpringBoot 項目是經常變換的,那麼應該怎麼利用緩存機制來實現呢?如果強行利用緩存那麼每次打的鏡像不都是緩存中的舊的程序內容嗎。

所以就考慮一下應用 Jar 包裡面都包含了什麼文件, Java 的哪些文件是經常變動的,哪些不經常變動,對此,下面將針對 SpringBoot 打的應用 Jar 包進行分析。

1、解壓 Jar 包查看內容

顯示解壓後的列表,查看各個文件夾大小

<code>$ 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/<code>

可以看到最大的文件就是 lib 這個文件夾,打開這個文件夾,裡面是一堆相關依賴 Jar,這其中一個 Jar 不大,但是一堆 Jar 組合起來就非常大了,一般 SpringBoot 的項目依賴 Jar 大小維持在 40MB ~ 160MB。

SpringBoot 項目構建 Docker 鏡像調優實踐

在看看 org 文件夾,裡面代碼加起來才幾百 KB。故此 SpringBoot 程序 Jar 包就是這些 Classes 文件和依賴的 Jar 組成,這些依賴 Jar 總共 74 MB,幾乎佔了這個應用 Jar 包的全部大小。

SpringBoot 項目構建 Docker 鏡像調優實踐

2、解決臃腫的新思路

如果一個 Jar 包只包含 class 文件,那麼這個 Jar 包的大小可能就幾百 KB。現在要探究一下,如果將 lib 依賴的 Jar 和 class 分離,設置應用的 Jar 包只包含 class 文件,將 lib 文件夾下的 Jar 文件放在 SpringBoot Jar 的外面。

當我們寫一個程序的時候,常常所依賴的 Jar 不會經常變動,變動多的是源代碼程序,依賴的 Jar 包非常大而源代碼非常小。

仔細思考一下,如果在打包成 Docker 鏡像的時候將應用依賴的 Jar 包單獨設置一層緩存,而應用 Jar 包只包含 Class 文件,這樣在 Docker 執行編譯、推送、拉取過程中,除了第一次是全部都要執行外,再往後的執行編譯、推送、拉取過程中,只會操作改動的那個只包含 Class 的 Jar 文件,就幾百 KB,可以說是能夠瞬間完成這個過程。所以思考一下,如何將 lib 文件夾下的依賴 Jar 包和應用 Jar 包分離開來。

SpringBoot 項目構建 Docker 鏡像調優實踐

3、如何解決 lib 和 class 文件分離

經過查找很多相關資料,發現 SpringBoot 的 Maven 插件在執行 Maven 編譯打 Jar 包時候做了很多事情,如果改變某些插件的打包邏輯,致使打應用 Jar 時候將 lib 文件夾下所有的 Jar 包都拷貝到應用 Jar 外面,只留下編譯好的字節碼文件。

將這幾個 Maven 工具引入到項目 pom.xml 中

<code><build>    <plugins>                <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>                <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>                <plugin>            <groupid>org.apache.maven.plugins/<groupid>            <artifactid>maven-dependency-plugin/<artifactid>            <executions>                <execution>                    copy-dependencies                    <phase>prepare-package/<phase>                    <goals>                        <goal>copy-dependencies/<goal>                    /<goals>                    <configuration>                        <outputdirectory>${project.build.directory}/lib/<outputdirectory>                    /<configuration>                /<execution>            /<executions>        /<plugin>    /<plugins>/<build>/<code>

執行 Maven 命令打包 Jar

<code>$ mvn clean install/<code>

當 Maven 命令執行完成後,查看 target 目錄如下圖:

SpringBoot 項目構建 Docker 鏡像調優實踐

然後測試下這個 Jar 文件是否能正常運行

<code>$ java -jar springboot-helloworld-0.0.1.jar/<code>

然後看到運行日誌,OK!下面將繼續進行 Dockerfile 改造工作。

四、聊聊如何改造 Springboot 編譯 Docker 鏡像

SpringBoot 項目構建 Docker 鏡像調優實踐

項目 Github 地址:https://github.com/my-dlq/blog-example/tree/master/springboot-dockerfile

1、修改 Dockerfile 文件

這裡修改上面的 Dockerfile 文件,需要新增一層指令用於將 lib 目錄裡面的依賴 Jar 複製到鏡像中,其它保持和上面 Dockerfile 一致。

<code>FROM openjdk:8u212-b04-jre-slimVOLUME /tmpCOPY target/lib/ ./lib/ADD target/*.jar app.jarRUN sh -c 'touch /app.jar'ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai"ENV APP_OPTS=""ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]/<code>

這裡新增了一層指令,作用為將 lib 文件夾複製到鏡像之中,由於 Docker 緩存機制原因,這層一定要在複製應用 Jar 之前,這樣改造後每次只要 lib/ 文件夾裡面的依賴 Jar 不變,就不會新創建層,而是複用緩存。

2、改造 Docker 鏡像後的首次編譯、推送、拉取

在執行編譯、推送、拉取之前,先將服務器上次鏡像相關的所有資源都清除掉,然後再執行。

(1)、編譯

<code>$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1 .Sending build context to Docker daemon  223.2MBStep 1/8 : FROM openjdk:8u212-b04-jre-slim8u212-b04-jre-slim: Pulling from library/openjdk743f2d6c1f65: Already exists b83e581826a6: Pull complete 04305660f45e: Pull complete bbe7020b5561: Pull complete Digest: sha256:a5bcd678408a5fe94d13e486d500983ee6fa594940cbbe137670fbb90030456cStatus: Downloaded newer image for openjdk:8u212-b04-jre-slim ---> 7c6b62cf60eeStep 2/8 : VOLUME /tmp ---> Running in 529369acab24Removing intermediate container 529369acab24 ---> ad689d937118Step 3/8 : COPY target/lib/ ./lib/ ---> 029a64c15853Step 4/8 : ADD target/*.jar app.jar ---> 6265a83a1b90Step 5/8 : RUN sh -c 'touch /app.jar' ---> Running in 839032a58e6bRemoving intermediate container 839032a58e6b ---> 5d877dc35b2bStep 6/8 : ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ---> Running in 4043994c5fedRemoving intermediate container 4043994c5fed ---> 7cf32beb571fStep 7/8 : ENV APP_OPTS="" ---> Running in b7dcfa10458aRemoving intermediate container b7dcfa10458a ---> b6b332bcf0e6Step 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ] ---> Running in 539093461b59Removing intermediate container 539093461b59 ---> d4c095c4ffecSuccessfully built d4c095c4ffecSuccessfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1real    0m22.983suser    0m0.051ssys 0m0.540s/<code>

(2)、推送

<code>$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1The push refers to repository [registry.cn-beijing.aliyuncs.com/mydlq/springboot]c16749205e05: Pushed 7fef1a146748: Pushed a3bae74bbdf2: Pushed 9544e87fb8dc: Pushedfeb5d0e1e192: Pushed8fd22162ddab: Pushed6270adb5794c: Pushed 0.0.1: digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157 size: 1789real    0m30.335suser    0m0.052ssys 0m0.059s/<code>

(3)、拉取

<code>$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.10.0.1: Pulling from mydlq/springboot743f2d6c1f65: Already exists b83e581826a6: Pull complete 04305660f45e: Pull complete bbe7020b5561: Pull complete de6c4f15d75b: Pull complete 7066947b7d89: Pull complete e0742de67c75: Pull complete Digest: sha256:e2f4db740880dbe5338b823112ba9467fedf8b27cd75572611d0d3837c80f157Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.1real    0m36.585suser    0m0.024ssys 0m0.092s/<code>

3、再次編譯、推送、拉取

(1)、編譯

<code>$ time docker build -t registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2 .Sending build context to Docker daemon  223.2MBStep 1/8 : FROM openjdk:8u212-b04-jre-slim ---> 7c6b62cf60eeStep 2/8 : VOLUME /tmp ---> Using cache ---> ad689d937118Step 3/8 : COPY target/lib/ ./lib/ ---> Using cache ---> 029a64c15853Step 4/8 : ADD target/*.jar app.jar ---> 563773953844Step 5/8 : RUN sh -c 'touch /app.jar' ---> Running in 3b9df57802bdRemoving intermediate container 3b9df57802bd ---> 706a0d47317fStep 6/8 : ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ---> Running in defda61452bfRemoving intermediate container defda61452bf ---> 742c7c926374Step 7/8 : ENV APP_OPTS="" ---> Running in f09b81d054ddRemoving intermediate container f09b81d054dd ---> 929ed5f8b12aStep 8/8 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ] ---> Running in 5dc66a8fc1e6Removing intermediate container 5dc66a8fc1e6 ---> c4942b10992cSuccessfully built c4942b10992cSuccessfully tagged registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2real    0m2.524suser    0m0.051ssys 0m0.493s/<code> 

可以看到,這次在第 3 層直接用的緩存,整個編譯過程才花了 2.5 秒時間

(2)、推送

<code>$ time docker push registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2The 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: 1789real    0m0.168suser    0m0.016ssys 0m0.032s/<code>

可以看到在 0.2s 內就完成了鏡像推送

(3)、拉取

<code>$ time docker pull registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.20.0.2: Pulling from mydlq/springboot743f2d6c1f65: Already exists b83e581826a6: Already exists 04305660f45e: Already exists bbe7020b5561: Already exists de6c4f15d75b: Already exists 1c77cc70cc41: Pull complete aa5b8cbca568: Pull complete Digest: sha256:b46d81b153ec64321caaae7ab28da0e362ed7d720a7f0775ea8d1f7bef310d00Status: Downloaded newer image for registry.cn-beijing.aliyuncs.com/mydlq/springboot:0.0.2real    0m1.947suser    0m0.017ssys 0m0.042s/<code>

可以看到在 2s 內就完成了鏡像拉取

五、最後總結

由於網絡波動和系統變化,所以時間只能當做參考,不過執行編譯、推送、拉取過程的確快了不少,大部分用文件都進行了緩存,只有幾百 KB 的流量交互自然速度比幾十 MB 甚至幾百 MB 速度要快很多。

最後說明一下,這種做法只是提供了一種參考,現在的微服務服務 Docker 鏡像化以來,維護的是整個鏡像而不是一個服務程序,所以關心的是 Docker 鏡像能否能正常運行,怎麼構建鏡像會使構建的鏡像更好用。

在生產環境下由於版本變化較慢,不會動不動就更新,所以在生產環境下暫時最好還是按部就班,應用原來 SpringBoot 鏡像編譯方式以確保安裝(除非已大量實例驗證該構建方法)。

END


分享到:


相關文章: