更新時間:2022-08-11 來源:黑馬程序員 瀏覽量:
一、序言
近幾年,微服務已經(jīng)成為Java主流的技術方向,隨著微服務化的流行,應用容器化部署也是必不可少的。應用容器化用抽象的話來說就是:將應用程序部署到容器當中作為獨立的應用程序部署單元運行,并作為實現(xiàn)高級別資源隔離的機制。常見的容器化技術就是docker,所以簡單來說就是將微服務程序打包成鏡像,在容器中運行,但這樣做有一個關鍵問題,就是docker鏡像越大,部署的效率越低,希望通過本文為你容器化部署提供效率。
二、 使用原始的方式構建一個docker鏡像
我們先用原始的方式制作一個Spring boot應用程序鏡像,體會一下目前流行的容器化部署方式。
1.創(chuàng)建spring boot應用
我們編寫一個簡單的應用程序,只有一個hello的controller即可
如果你不想創(chuàng)建該項目,[可以從這里看到源碼](https://gitee.com/jk1123/docker-jib-test/tree/master)
打開瀏覽器簡單測試一下:
2. 打包
root@ubuntu:docker-image-demo$ mvn package
3.編寫Dockerfile
#Dockerfile 這里我們選用 jre環(huán)境 減少鏡像的體積 FROM openjdk:8-jre-alpine #鏡像內(nèi)部創(chuàng)建一個app目錄 用來存放jar包 RUN mkdir /app #復制jar包 到app目錄下 COPY target/docker-image-demo-0.0.1-SNAPSHOT.jar /app/app.jar #暴露端口 EXPOSE 8080/tcp #默認啟動程序 ENTRYPOINT java -jar /app/app.jar
4. 創(chuàng)建鏡像
#創(chuàng)建鏡像 root@ubuntu:docker-image-demo$ docker build -t docker-image-demo:0.0.1 . #查詢鏡像 root@ubuntu:docker-image-demo$ docker images
5. 推送鏡像到registry倉庫
#將鏡像推送到鏡像倉庫 這里我們選擇阿里云的鏡像倉庫 #登錄的步驟 請自行查閱阿里云鏡像倉庫 root@ubuntu:docker-image-demo$ docker tag docker-image-demo:0.0.1 registry.cn-hangzhou.aliyuncs.com/jk1123/docker-jib-test:0.0.1 #推送 root@ubuntu:docker-image-demo$ docker push registry.cn-hangzhou.aliyuncs.com/jk1123/docker-jib-test:0.0.1
在阿里云倉庫查看鏡像
三、原始方式的不足
1.需要編寫Dockerfile
鏡像的打包部署本身屬于運維工作,但是需要開發(fā)人員的介入,解放應用開發(fā)人員的雙手,不要將運維的工作引入到開發(fā)人員的工作流中。
2. 制作鏡像耗時
使用springboot的項目打包而成的jar包是一個fat jar(就是該jar中包含該應用程序需要一切依賴).導致docker鏡像制作過程當中需要復制該jar到容器中。
稍微大一點應用程序打成fat jar 高達一兩百MB,其實最主要還是依賴的sprring全家桶的jar太多。
3. 推送鏡像到倉庫和拉取鏡像耗時
微服務的使用便于快速迭代服務,所以發(fā)版的頻率十分頻繁.每次推送鏡像/拉取鏡像十分耗時,因為每次發(fā)版我們的fat jar都會發(fā)生細微的改變.導致docker無法利用其緩存機制,每次都要拉取鏡像中的fat jar 那層.導致推送和拉取十分消耗網(wǎng)絡資源和時間。
四、 使用Google jib工具
1. 簡介
Jib 是谷歌公司推出的開源 Java 鏡像構建工具,它可以將一個 Java 應用構建成 OCI 鏡像或者是 Docker 鏡像,目前最新的 Relaese 版本為 3.2.1
JIB 具有以下特點:
1. Jib 使用 Java 開發(fā),并作為 Maven 或 Gradle 的一部分運行.你不需要編寫 Dockerfile 或 安裝Docker 環(huán)境,甚至無需創(chuàng)建包含所有依賴的大 JAR 包,就可以構建出鏡像,并將鏡像推送到鏡像倉庫。因為 Jib 與 Java 構建過程緊密集成,所以它可以訪問到打包應用程序所需的所有信息。在后續(xù)的容器構建期間,它將自動選擇 Java 構建過的任何變體。
2. JIB 構建出的應用鏡像,具有分層結構, 利用鏡像分層和注冊表緩存來實現(xiàn)快速、增量的構建,提高構建鏡像、推送鏡像的性能,減少鏡像存儲空間。
3. 冪等性,Jib 支持根據(jù) Maven 和 Gradle 的構建元數(shù)據(jù)進行聲明式的[容器鏡像](https://cloud.tencent.com/product/tcr?from=10680)構建,只要輸入保持不變,就可以通過配置重復創(chuàng)建相同的鏡像。
下圖是官方給出的性能測試
2.使用
如此強大的工具使用起來相當?shù)暮唵?br/>
2.1 導入插件依賴
<!-- pom文件中添加jib的插件--> <plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>3.2.0</version> </plugin>
2.2 配置插件
<plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>3.2.0</version> <configuration> <from> <!--基礎鏡像名字--> <image>openjdk:8-jre-alpine</image> </from> <to> <image>registry.cn-hangzhou.aliyuncs.com/jk1123/docker-jib-test</image> <tags> <tag>0.0.2</tag> </tags> <!--<auth>--> <!--<username>自己倉庫的賬號</username>--> <!--<password>寫自己的倉庫密碼</password>--> <!--</auth>--> <!-- 其實這里還是建議 使用maven-setting的配置方式 請參照 https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#authentication-methods https://maven.apache.org/guides/mini/guide-encryption.html --> </to> <container> <!--指明主類--> <mainClass>com.jk1123.docker.DockerImageDemoApplication</mainClass> <creationTime>USE_CURRENT_TIMESTAMP</creationTime> <jvmFlags> <jvmFlag>-Dmy.property=example.value</jvmFlag> <jvmFlag>-Xms512m</jvmFlag> <jvmFlag>-Xmx2048m</jvmFlag> </jvmFlags> <ports> <port>8080</port> </ports> <labels> <org.label-schema.schema-version>1.0</org.label-schema.schema-version> <org.label-schema.name>docker-image-test</org.label-schema.name> <org.label-schema.vendor>jk1123</org.label-schema.vendor> <org.label-schema.license>GPLv2</org.label-schema.license> <org.label-schema.build-date>${maven.build.timestamp}</org.label-schema.build-date> <org.opencontainers.image.title>docker-image-test Image</org.opencontainers.image.title> <org.opencontainers.image.vendor>jk1123</org.opencontainers.image.vendor> <org.opencontainers.image.licenses>GPL-2.0-only</org.opencontainers.image.licenses> <org.opencontainers.image.created>${maven.build.timestamp}</org.opencontainers.image.created> </labels> </container> <allowInsecureRegistries>true</allowInsecureRegistries> </configuration> <executions> <execution> <phase>package</phase> <goals> <!-- 本地構建這個--> <!--<goal>dockerBuild</goal>--> <!-- 遠程構建是這個--> <goal>build</goal> </goals> </execution> </executions> </plugin>
2.3.執(zhí)行構建
root@ubuntu:docker-image-demo$ mvn package jib:build
五、 JIB原理分析
1. docker鏡像緩存
docker的鏡像是由一層層構成的
我們?nèi)绻捎迷挤绞酱虬R像,鏡像分層如圖.在這種情況下,如果我們的代碼有變化,就會重新制作一個springboot的fat jar,這個jar中即時只有一行代碼改變了,生成的新的jar也與原來的文件也變化,docker制作鏡像的時候 該層發(fā)生了變化就需要重新制作,而一個fat jar非常的大,無法利用鏡像的緩存功能。
2. jib構建鏡像分層
Jib 在編譯 springboot應用的時候考慮到的docker鏡像的緩存功能,能利用緩存盡量的利用鏡像的緩存。
通過分析我們會發(fā)現(xiàn)如下規(guī)律:
1.應用代碼是最容易發(fā)生變化的,但是代碼文件實際占用并不是太高(相對于引入jar包大小而言)
2.應用的配置文件也容易發(fā)生變化,但是變化頻率相對于代碼要低一些
3.應用依賴的其他的公共子模塊也容易發(fā)生變化,但是變化頻率相對于代碼要更低一些
4.應用依賴的一些快照jar包也容易發(fā)生變化,頻率更低
5.應用依賴的常規(guī)jar,例如spring系列的jar包,變化頻率不大,試想誰會天天換spring版本號呢
綜上所述,jib的作者充分考慮到這些規(guī)律,將鏡像分成好幾層,充分利用的docker鏡像緩存機制和資源的變化頻率的特性,接下來我們來看看使用jib制作的鏡像的層級關系圖
首先我們先看看我們的項目結構
接下來我們來看看鏡像的層級結構圖
可見jib充分考慮和利用的docker鏡像緩存的機制,來幫我們制作鏡像.這樣當我們的應用重新發(fā)版的時候,可以減少鏡像的push和pull的速度。
注:
上圖分析工具使用dive工具
關于dive工具的使用請參照這里:
github:https://github.com/wagoodman/dive
gitee:https://gitee.com/mirrors/Dive
六、 結束語
通過如上的分析,相信大家對jib插件有個清晰的認知:
jib就是根據(jù)應用的不同資源的變化頻率和docker鏡像的緩存機制,充分利用docker鏡像的分層機制.提高鏡像的制作和發(fā)布性能.
最后,希望各位讀者早日用上jib來打包您的應用,減少鏡像的體積,減少打包消耗,減少傳輸消耗,暢享綠色生活!!!