首頁(yè)技術(shù)文章正文

Java培訓(xùn):使用Jib插件容器化SpringBoot應(yīng)用

更新時(shí)間:2022-08-11 來(lái)源:黑馬程序員 瀏覽量:

  一、序言

   近幾年,微服務(wù)已經(jīng)成為Java主流的技術(shù)方向,隨著微服務(wù)化的流行,應(yīng)用容器化部署也是必不可少的。應(yīng)用容器化用抽象的話來(lái)說(shuō)就是:將應(yīng)用程序部署到容器當(dāng)中作為獨(dú)立的應(yīng)用程序部署單元運(yùn)行,并作為實(shí)現(xiàn)高級(jí)別資源隔離的機(jī)制。常見的容器化技術(shù)就是docker,所以簡(jiǎn)單來(lái)說(shuō)就是將微服務(wù)程序打包成鏡像,在容器中運(yùn)行,但這樣做有一個(gè)關(guān)鍵問題,就是docker鏡像越大,部署的效率越低,希望通過(guò)本文為你容器化部署提供效率。

  二、 使用原始的方式構(gòu)建一個(gè)docker鏡像

  我們先用原始的方式制作一個(gè)Spring boot應(yīng)用程序鏡像,體會(huì)一下目前流行的容器化部署方式。

       1.創(chuàng)建spring boot應(yīng)用

  我們編寫一個(gè)簡(jiǎn)單的應(yīng)用程序,只有一個(gè)hello的controller即可

  

1660184325498_1.jpg

  如果你不想創(chuàng)建該項(xiàng)目,[可以從這里看到源碼](https://gitee.com/jk1123/docker-jib-test/tree/master)

  打開瀏覽器簡(jiǎn)單測(cè)試一下:

  

1660184356319_2.jpg

  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目錄 用來(lái)存放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)啟動(dòng)程序
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

  

1660184499608_3.jpg

  5. 推送鏡像到registry倉(cāng)庫(kù)

#將鏡像推送到鏡像倉(cāng)庫(kù) 這里我們選擇阿里云的鏡像倉(cāng)庫(kù) 
#登錄的步驟 請(qǐng)自行查閱阿里云鏡像倉(cāng)庫(kù)

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

  

1660184610101_4.jpg

  在阿里云倉(cāng)庫(kù)查看鏡像

  

1660184627029_5.jpg

  三、原始方式的不足

      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鏡像制作過(guò)程當(dāng)中需要復(fù)制該jar到容器中。

  稍微大一點(diǎn)應(yīng)用程序打成fat jar 高達(dá)一兩百M(fèi)B,其實(shí)最主要還是依賴的sprring全家桶的jar太多。

  3. 推送鏡像到倉(cāng)庫(kù)和拉取鏡像耗時(shí)

  微服務(wù)的使用便于快速迭代服務(wù),所以發(fā)版的頻率十分頻繁.每次推送鏡像/拉取鏡像十分耗時(shí),因?yàn)槊看伟l(fā)版我們的fat jar都會(huì)發(fā)生細(xì)微的改變.導(dǎo)致docker無(wú)法利用其緩存機(jī)制,每次都要拉取鏡像中的fat jar 那層.導(dǎo)致推送和拉取十分消耗網(wǎng)絡(luò)資源和時(shí)間。

  四、 使用Google jib工具

  1. 簡(jiǎn)介

  

1660184711954_6.jpg

  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)境,甚至無(wú)需創(chuàng)建包含所有依賴的大 JAR 包,就可以構(gòu)建出鏡像,并將鏡像推送到鏡像倉(cāng)庫(kù)。因?yàn)?Jib 與 Java 構(gòu)建過(guò)程緊密集成,所以它可以訪問到打包應(yīng)用程序所需的所有信息。在后續(xù)的容器構(gòu)建期間,它將自動(dòng)選擇 Java 構(gòu)建過(guò)的任何變體。

  2. JIB 構(gòu)建出的應(yīng)用鏡像,具有分層結(jié)構(gòu), 利用鏡像分層和注冊(cè)表緩存來(lái)實(shí)現(xiàn)快速、增量的構(gòu)建,提高構(gòu)建鏡像、推送鏡像的性能,減少鏡像存儲(chǔ)空間。

  3. 冪等性,Jib 支持根據(jù) Maven 和 Gradle 的構(gòu)建元數(shù)據(jù)進(jìn)行聲明式的[容器鏡像](https://cloud.tencent.com/product/tcr?from=10680)構(gòu)建,只要輸入保持不變,就可以通過(guò)配置重復(fù)創(chuàng)建相同的鏡像。

  下圖是官方給出的性能測(cè)試

  

1660184766802_7.jpg

  

1660184780438_8.jpg

  2.使用

  如此強(qiáng)大的工具使用起來(lái)相當(dāng)?shù)暮?jiǎn)單

  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>自己倉(cāng)庫(kù)的賬號(hào)</username>-->
            <!--<password>寫自己的倉(cāng)庫(kù)密碼</password>-->
            <!--</auth>-->
            <!--
             其實(shí)這里還是建議 使用maven-setting的配置方式 請(qǐng)參照
             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

  

1660184928080_9.jpg

  五、 JIB原理分析

  1. docker鏡像緩存

  docker的鏡像是由一層層構(gòu)成的

  我們?nèi)绻捎迷挤绞酱虬R像,鏡像分層如圖.在這種情況下,如果我們的代碼有變化,就會(huì)重新制作一個(gè)springboot的fat jar,這個(gè)jar中即時(shí)只有一行代碼改變了,生成的新的jar也與原來(lái)的文件也變化,docker制作鏡像的時(shí)候 該層發(fā)生了變化就需要重新制作,而一個(gè)fat jar非常的大,無(wú)法利用鏡像的緩存功能。

  2. jib構(gòu)建鏡像分層

  Jib 在編譯 springboot應(yīng)用的時(shí)候考慮到的docker鏡像的緩存功能,能利用緩存盡量的利用鏡像的緩存。

  通過(guò)分析我們會(huì)發(fā)現(xiàn)如下規(guī)律:

  1.應(yīng)用代碼是最容易發(fā)生變化的,但是代碼文件實(shí)際占用并不是太高(相對(duì)于引入jar包大小而言)

  2.應(yīng)用的配置文件也容易發(fā)生變化,但是變化頻率相對(duì)于代碼要低一些

  3.應(yīng)用依賴的其他的公共子模塊也容易發(fā)生變化,但是變化頻率相對(duì)于代碼要更低一些

  4.應(yīng)用依賴的一些快照jar包也容易發(fā)生變化,頻率更低

  5.應(yīng)用依賴的常規(guī)jar,例如spring系列的jar包,變化頻率不大,試想誰(shuí)會(huì)天天換spring版本號(hào)呢

  綜上所述,jib的作者充分考慮到這些規(guī)律,將鏡像分成好幾層,充分利用的docker鏡像緩存機(jī)制和資源的變化頻率的特性,接下來(lái)我們來(lái)看看使用jib制作的鏡像的層級(jí)關(guān)系圖

  首先我們先看看我們的項(xiàng)目結(jié)構(gòu)

  

1660185036673_11.jpg

  接下來(lái)我們來(lái)看看鏡像的層級(jí)結(jié)構(gòu)圖

  

  可見jib充分考慮和利用的docker鏡像緩存的機(jī)制,來(lái)幫我們制作鏡像.這樣當(dāng)我們的應(yīng)用重新發(fā)版的時(shí)候,可以減少鏡像的push和pull的速度。

  注:

  上圖分析工具使用dive工具

  關(guān)于dive工具的使用請(qǐng)參照這里:

  github:https://github.com/wagoodman/dive

  gitee:https://gitee.com/mirrors/Dive

  六、 結(jié)束語(yǔ)

  通過(guò)如上的分析,相信大家對(duì)jib插件有個(gè)清晰的認(rèn)知:

  jib就是根據(jù)應(yīng)用的不同資源的變化頻率和docker鏡像的緩存機(jī)制,充分利用docker鏡像的分層機(jī)制.提高鏡像的制作和發(fā)布性能.

  最后,希望各位讀者早日用上jib來(lái)打包您的應(yīng)用,減少鏡像的體積,減少打包消耗,減少傳輸消耗,暢享綠色生活!!!

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!