天天看點

容器化部署 Jib概念原理使用工作中

概念

Google Jib 容器化建構工具

Jib

google

開源的

Java容器化工具

,可以

直接建構 Java 應用

Docker 和 OCI 鏡像的類庫

,以

Maven 和 Gradle 插件

形式提供。

通過 Jib

,Java 開發者可以

使用他們熟悉的 Java 工具來建構容器

。Jib 是一個

快速而簡單

的容器鏡像建構工具,它負責處理

将應用程式打包到容器鏡像中所需的所有步驟

。它

不需要你編寫 Dockerfile 或安裝 Docker

,而且可以

直接內建到 Maven 和 Gradle中

——

隻需要将插件添加到建構中,就可以立即将 Java 應用程式容器化

Docker 建構流程

容器化部署 Jib概念原理使用工作中

Jib 建構流程

容器化部署 Jib概念原理使用工作中

簡單

——Jib使用Java開發,并作為

Maven或Gradle的一部分運作

。你

不需要編寫Dockerfile或運作Docker守護程序,甚至無需建立包含所有依賴的大JAR包

。因為

Jib與Java建構過程緊密內建

,是以它

可以通路到打包應用程式所需的所有資訊

。在後續的容器建構期間,它将自動選擇Java建構過的任何變體。

快速

——Jib利用

鏡像分層

系統資料庫緩存

實作快速、增量的建構

。它

讀取你的建構配置

,将你的

應用程式組織到不同的層

(依賴項、資源、類)中,并隻

重新建構和推送發生變更的層

。在項目進行快速疊代時,

Jib隻将發生變更的層(而不是整個應用程式)推送到系統資料庫來節省寶貴的建構時間

可重制

——Jib支援

根據Maven和Gradle的建構中繼資料進行聲明式的容器鏡像建構

,是以,隻要輸入保持不變,就可以

通過配置重複建立相同的鏡像

簡化

快速 — 快速部署您的更改。Jib 将你的應用程式分成多個層,從類中分離依賴項。你不必等待 Docker 重建整個 Java 應用程式 —— 隻需部署更改的層即可

可重制 — 使用相同内容重建容器鏡像

Daemonless — 減少 CLI 依賴性。從 Maven 或 Gradle 中建構 Docker 鏡像,然後推送到你選擇的任何系統資料庫,無需編寫 Dockerfiles 并調用 docker build/push
           

下圖為某

微服務開啟 Jib 建構後在 Jenkins 中的建構過程

,可以看出

建構速度的提升主要在 package 和 push 階段

容器化部署 Jib概念原理使用工作中

原理

假設我們有一個項目,其組織結構如下:

parentPro
    |-- moduleA
    |-- moduleB
    |-- rest    [rest 子產品為 spring boot 啟動入口,并依賴 moduleA、moduleB]
           

對于

SpringBoot 項目

,Maven 的

預設建構工具

Spring-boot-maven-plugin

,建構出

産物為

Fat Jar

Fat jar

中包含有

rest 子產品中的 classes

,及

rest 所依賴的 moduleA、moduleB

及其他

第三方 jar 庫

。最終,通過

Jenkins

Dockerfile

檔案将 Fat jar 基于 JDK 基礎鏡像層建構,産生一個新的應用鏡像。

每次應用建構新版本鏡像時,因為 Maven 建構産出物是 Fat jar,當 rest、moduleA、moduleB 子產品中任意一處發生變化時,都會産出一個新的 Fat jar。建構鏡像時都要将整個 Fat jar 重新寫入到鏡像層,并将整個鏡像層推送到鏡像倉庫中,大大降低了鏡像建構和推送的性能,并導緻同一個應用鏡像的多個 Tag 占用大量的存儲空間。

Jib 在

編譯 Java 應用時

,會

将 Java 項目

内的

資源及所依賴的資源

基于變化頻率不同分成多個部分

,并

将每個部分都單獨作為一個鏡像層

存在,這樣

其中一部分資源發生變化

時,

隻需要重新建構該部分所屬鏡像層即可

以第二節的應用為例,rest 應用鏡像将被分為以下鏡像層:

Classes

: rest 子產品中的

class

資訊,這部分資訊

變化頻率最高

,處于

最上層鏡像層

Resources

: rest 子產品中的

配置檔案

,這部分資訊

變化頻率較低

,處于

第二層鏡像層

Project Dependencies

: rest 子產品的

項目依賴資訊

,在目前示例中為 moduleA、moduleB,這部分内容比依賴第三方 Jar 庫更容易變化,是以也單獨做為一個鏡像層存在;

Snapshot Dependencies

:rest 子產品所依賴的 SnapShot Jar 庫;

All other Dependencies

: rest 子產品所依賴的其他類型 Jar 庫;

Each extra directory

:其他所依賴額外資源目錄;

基于

Jib 插件建構出的鏡像,與使用以下 Dockerfile 所建構出的鏡像相同

容器化部署 Jib概念原理使用工作中

使用

關鍵幾步

配置 parent 的 pom

<properties>    
    <!-- 要想本地可以上傳到阿裡雲,請使用公網位址 registry.cn-shenzhen.aliyuncs.com -->
    <docker.repostory>registry-vpc.cn-shenzhen.aliyuncs.com</docker.repostory>
    <docker.repostory.namespace>syp-app</docker.repostory.namespace>
    <docker.project.version>1.0</docker.project.version>
</properties>
<build>
  <pluginManagement>
    <plugins>
      <!-- spring-boot-maven-plugin -->
      <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>1.7.0</version>
        <configuration>
          <!-- 拉取所需的基礎鏡像 - 即建構本鏡像所基于的根鏡像 -->
          <from>
            <image>${docker.repostory}/syp-common/openjdk:8-jdk-alpine</image>
            <auth>
                <username>在阿裡雲上的賬号</username>
                <password>阿裡雲注冊的密碼</password>
            </auth>
          </from>
          <!-- 最後生成的鏡像配置 -->
          <!-- 表示本鏡像建構完成後,要釋出到哪裡去 -->
          <to>
             <!-- push到阿裡雲鏡像倉庫,如果是其它鏡像倉庫,将下面位址替換掉即可,ex: `Docker Hub` 的 `docker.io/zhengqing/xxx` -->
             <!-- 鏡像名,命名格式為:Registry 倉庫位址/屬組/鏡像名:Tag名 -->
            <image>
              ${docker.repostory}/${docker.repostory.namespace}/${project.artifactId}
            </image>
            <tags>
                <tag>${docker.project.version}</tag>
                <tag>latest</tag>
            </tags>
            <!-- 阿裡雲的使用者名和密碼也可以配置在 maven settings.xml檔案中(推薦) -->
            <!--插件配置中的使用者密碼及鏡像庫位址在ci的環境變量中配置 -->
            <auth>
              	<username>在阿裡雲上的賬号</username>
                <password>阿裡雲注冊的密碼</password>
            </auth>
          </to>
          <container>
              <jvmFlags>
                  <jvmFlag>-Xms512m</jvmFlag>
                  <jvmFlag>-Xmn256m</jvmFlag>
              </jvmFlags>
              <environment>
                  <TZ>Asia/Shanghai</TZ>
              </environment>
              <useCurrentTimestamp>true</useCurrentTimestamp>
          </container>
          <!--允許使用 HTTP 協定連接配接 Registry 倉庫-->
          <allowInsecureRegistries>true</allowInsecureRegistries>
        </configuration>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                  	<goal>build</goal>
                </goals>
            </execution>
        </executions>
      </plugin>
    </plugins>
  </pluginManagement>
</build>
           

配置 module 的 pom

<parent>
	    <groupId>com.missyou</groupId>
	    <artifactId>missyou</artifactId>
	    <version>1.0-SNAPSHOT</version>
	</parent>
	<groupId>com.missyou</groupId>
	<artifactId>missyou_user_service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<build>
	    <finalName>missyou_user_service</finalName>
	    <plugins>
	        <!-- spring-boot-maven-plugin -->
	        <!-- maven-compiler-plugin -->
	        <plugin>
	            <groupId>com.google.cloud.tools</groupId>
	            <artifactId>jib-maven-plugin</artifactId>
	        </plugin>
	    </plugins>
	</build>

           

配置maven settings.xml檔案(推薦)

<pluginGroups>
    <pluginGroup>com.google.cloud.tools</pluginGroup>
</pluginGroups>
<!--對應容器倉庫權限的賬号密碼-->
<servers>
    <server>
        <id>registry-vpc.cn-shenzhen.aliyuncs.com</id>
        <username>xxx</username>
        <password>xxx</password>
    </server>
</servers>
           

配置 .gitlab-ci.yml

image: xxx.com/xxx-tools/cibase:0.5.0
variables:
    MAVEN_OPTS: -Dmaven.repo.local=.m2/repository
    BUILD_CI_NAME: $CI_COMMIT_REF_NAME-$CI_PIPELINE_ID
stages:
- build
- dev-release
 
cache:
    key: one-key-for-all
    paths:
        - .m2/repository/
 
build:
    stage: build
    script: "mvn -U clean compile"
 
dev-release:
    stage: dev-release
    only:
    - tags
    - development-uat
    - /^release-.*$/
    when: manual
    script:
    - "mvn compile jib:build -Dregistry_url=$REGISTRY_URL -Dregistry_username=$REGISTRY_USERNAME -Dregistry_password=$REGISTRY_PASSWORD -Dci_pipeline_id=$BUILD_CI_NAME"
           

配置完畢後,使用如下指令編譯,并

自動 push 到倉庫中

mvn clean package -DskipTests jib:build

核心就是 jib:build,更多指令見文檔: https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#build-your-image
           

鑒權

根據錯誤日志可知連接配接 Registry 倉庫時需要鑒權

容器化部署 Jib概念原理使用工作中

maven 報錯

解決-指令行

最粗暴的,在

執行 maven 指令時傳遞 Registry 倉庫的使用者名密碼

mvn clean package -DskipTests jib:build \
    -Djib.from.auth.username=admin \
    -Djib.from.auth.password=admin \
    -Djib.to.auth.username=admin \
    -Djib.to.auth.password=admin
           

由于

<from> 和 <to> 中的鏡像

可能不是來自于同一個 Registry 倉庫

,是以既要配置 from 的使用者名密碼,也要配置 to 的使用者名密碼。

執行完畢後,通過指令行,或者

可視化工具

,檢視

是否被 push 上去

(此處我使用的工具是

Harbor

容器化部署 Jib概念原理使用工作中

解決-配置檔案

使用指令行方式每次執行都要輸入那麼長一串指令,這樣實在是不友善。另一種方法是

在 pom.xml 檔案直接将使用者名密碼配置進去

<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>jib-maven-plugin</artifactId>
  <version>1.8.0</version>
  <configuration>
    <from>
      <image>harbor.jitwxs-inc.com/base/java:8-jdk-alpine</image>
      <auth>
        <username>my_username</username>
        <password>my_password</password>
      </auth>
    </from>
    <to>
      <image>harbor.jitwxs-inc.com/sample/${artifactId}:v1</image>
      <auth>
        <username>my_username</username>
        <password>my_password</password>
      </auth>
    </to>
    <allowInsecureRegistries>true</allowInsecureRegistries>
  </configuration>
</plugin>
           

給 from 和 to 标簽都加上 <auth> 标簽

,但是這種方式實在是

不夠優雅

,因為

将使用者名密碼寫死在代碼中會帶來安全性問題

合适的方法

合适的方法是配置

在 Maven 的 settings.xml 配置檔案中

,在

<servers> 标簽中新增一個 <server> 節點

配置 Registry 倉庫的使用者名密碼

<servers>
    ...
    <server>
      <id>harbor.jitwxs-inc.com</id>
      <username>admin</username>
      <password>admin</password>
      <configuration>
        <email>[email protected]</email>
      </configuration>
    </server>
</servers>
           

配置完畢後,再執行次指令驗證下:

mvn clean package -DskipTests jib:build
           

不想單獨輸入 jib:build

如果你

不想單獨輸入 jib:build

,你可以

把 jib 綁定到 Maven 指令中

,在

maven插件中添加

如下的

<executions>

标簽即可。

<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>jib-maven-plugin</artifactId>
  ...
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>build</goal>
      </goals>
    </execution>
  </executions>
</plugin>
           

mvn package 指令

就會自動建構鏡像

工作中

maven 中 pom 中标簽含義

檢視百度網盤

容器化部署 Jib概念原理使用工作中