更新時(shí)間:2022-08-11 來源:黑馬程序員 瀏覽量:
一、序言
近幾年,微服務(wù)已經(jīng)成為Java主流的技術(shù)方向,隨著微服務(wù)化的流行,應(yīng)用容器化部署也是必不可少的。應(yīng)用容器化用抽象的話來說就是:將應(yīng)用程序部署到容器當(dāng)中作為獨(dú)立的應(yīng)用程序部署單元運(yùn)行,并作為實(shí)現(xiàn)高級別資源隔離的機(jī)制。常見的容器化技術(shù)就是docker,所以簡單來說就是將微服務(wù)程序打包成鏡像,在容器中運(yùn)行,但這樣做有一個(gè)關(guān)鍵問題,就是docker鏡像越大,部署的效率越低,希望通過本文為你容器化部署提供效率。
二、 使用原始的方式構(gòu)建一個(gè)docker鏡像
我們先用原始的方式制作一個(gè)Spring boot應(yīng)用程序鏡像,體會一下目前流行的容器化部署方式。
1.創(chuàng)建spring boot應(yīng)用
我們編寫一個(gè)簡單的應(yīng)用程序,只有一個(gè)hello的controller即可
如果你不想創(chuàng)建該項(xià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)建一個(gè)app目錄 用來存放jar包 RUN mkdir /app #復(fù)制jar包 到app目錄下 COPY target/docker-image-demo-0.0.1-SNAPSHOT.jar /app/app.jar #暴露端口 EXPOSE 8080/tcp #默認(rèn)啟動程序 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
鏡像的打包部署本身屬于運(yùn)維工作,但是需要開發(fā)人員的介入,解放應(yīng)用開發(fā)人員的雙手,不要將運(yùn)維的工作引入到開發(fā)人員的工作流中。
2. 制作鏡像耗時(shí)
使用springboot的項(xiàng)目打包而成的jar包是一個(gè)fat jar(就是該jar中包含該應(yīng)用程序需要一切依賴).導(dǎo)致docker鏡像制作過程當(dāng)中需要復(fù)制該jar到容器中。
稍微大一點(diǎn)應(yīng)用程序打成fat jar 高達(dá)一兩百M(fèi)B,其實(shí)最主要還是依賴的sprring全家桶的jar太多。
3. 推送鏡像到倉庫和拉取鏡像耗時(shí)
微服務(wù)的使用便于快速迭代服務(wù),所以發(fā)版的頻率十分頻繁.每次推送鏡像/拉取鏡像十分耗時(shí),因?yàn)槊看伟l(fā)版我們的fat jar都會發(fā)生細(xì)微的改變.導(dǎo)致docker無法利用其緩存機(jī)制,每次都要拉取鏡像中的fat jar 那層.導(dǎo)致推送和拉取十分消耗網(wǎng)絡(luò)資源和時(shí)間。
四、 使用Google jib工具
1. 簡介
Jib 是谷歌公司推出的開源 Java 鏡像構(gòu)建工具,它可以將一個(gè) Java 應(yīng)用構(gòu)建成 OCI 鏡像或者是 Docker 鏡像,目前最新的 Relaese 版本為 3.2.1
JIB 具有以下特點(diǎn):
1. Jib 使用 Java 開發(fā),并作為 Maven 或 Gradle 的一部分運(yùn)行.你不需要編寫 Dockerfile 或 安裝Docker 環(huán)境,甚至無需創(chuàng)建包含所有依賴的大 JAR 包,就可以構(gòu)建出鏡像,并將鏡像推送到鏡像倉庫。因?yàn)?Jib 與 Java 構(gòu)建過程緊密集成,所以它可以訪問到打包應(yīng)用程序所需的所有信息。在后續(xù)的容器構(gòu)建期間,它將自動選擇 Java 構(gòu)建過的任何變體。
2. JIB 構(gòu)建出的應(yīng)用鏡像,具有分層結(jié)構(gòu), 利用鏡像分層和注冊表緩存來實(shí)現(xiàn)快速、增量的構(gòu)建,提高構(gòu)建鏡像、推送鏡像的性能,減少鏡像存儲空間。
3. 冪等性,Jib 支持根據(jù) Maven 和 Gradle 的構(gòu)建元數(shù)據(jù)進(jìn)行聲明式的[容器鏡像](https://cloud.tencent.com/product/tcr?from=10680)構(gòu)建,只要輸入保持不變,就可以通過配置重復(fù)創(chuàng)建相同的鏡像。
下圖是官方給出的性能測試
2.使用
如此強(qiáng)大的工具使用起來相當(dāng)?shù)暮唵?br/>
2.1 導(dǎo)入插件依賴
<!-- 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> <!--基礎(chǔ)鏡像名字--> <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>--> <!-- 其實(shí)這里還是建議 使用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> <!-- 本地構(gòu)建這個(gè)--> <!--<goal>dockerBuild</goal>--> <!-- 遠(yuǎn)程構(gòu)建是這個(gè)--> <goal>build</goal> </goals> </execution> </executions> </plugin>
2.3.執(zhí)行構(gòu)建
root@ubuntu:docker-image-demo$ mvn package jib:build
五、 JIB原理分析
1. docker鏡像緩存
docker的鏡像是由一層層構(gòu)成的
我們?nèi)绻捎迷挤绞酱虬R像,鏡像分層如圖.在這種情況下,如果我們的代碼有變化,就會重新制作一個(gè)springboot的fat jar,這個(gè)jar中即時(shí)只有一行代碼改變了,生成的新的jar也與原來的文件也變化,docker制作鏡像的時(shí)候 該層發(fā)生了變化就需要重新制作,而一個(gè)fat jar非常的大,無法利用鏡像的緩存功能。
2. jib構(gòu)建鏡像分層
Jib 在編譯 springboot應(yīng)用的時(shí)候考慮到的docker鏡像的緩存功能,能利用緩存盡量的利用鏡像的緩存。
通過分析我們會發(fā)現(xiàn)如下規(guī)律:
1.應(yīng)用代碼是最容易發(fā)生變化的,但是代碼文件實(shí)際占用并不是太高(相對于引入jar包大小而言)
2.應(yīng)用的配置文件也容易發(fā)生變化,但是變化頻率相對于代碼要低一些
3.應(yīng)用依賴的其他的公共子模塊也容易發(fā)生變化,但是變化頻率相對于代碼要更低一些
4.應(yīng)用依賴的一些快照jar包也容易發(fā)生變化,頻率更低
5.應(yīng)用依賴的常規(guī)jar,例如spring系列的jar包,變化頻率不大,試想誰會天天換spring版本號呢
綜上所述,jib的作者充分考慮到這些規(guī)律,將鏡像分成好幾層,充分利用的docker鏡像緩存機(jī)制和資源的變化頻率的特性,接下來我們來看看使用jib制作的鏡像的層級關(guān)系圖
首先我們先看看我們的項(xiàng)目結(jié)構(gòu)
接下來我們來看看鏡像的層級結(jié)構(gòu)圖
可見jib充分考慮和利用的docker鏡像緩存的機(jī)制,來幫我們制作鏡像.這樣當(dāng)我們的應(yīng)用重新發(fā)版的時(shí)候,可以減少鏡像的push和pull的速度。
注:
上圖分析工具使用dive工具
關(guān)于dive工具的使用請參照這里:
github:https://github.com/wagoodman/dive
gitee:https://gitee.com/mirrors/Dive
六、 結(jié)束語
通過如上的分析,相信大家對jib插件有個(gè)清晰的認(rèn)知:
jib就是根據(jù)應(yīng)用的不同資源的變化頻率和docker鏡像的緩存機(jī)制,充分利用docker鏡像的分層機(jī)制.提高鏡像的制作和發(fā)布性能.
最后,希望各位讀者早日用上jib來打包您的應(yīng)用,減少鏡像的體積,減少打包消耗,減少傳輸消耗,暢享綠色生活!!!