容器化部署 java

概念 Google Jib 容器化构建工具 Jib 是google 开源的Java容器化工具 ,可以直接构建 Java 应用 的 Docker 和 OCI 镜像的类库 ,以 Maven 和 Gradle 插件 形式提供。 通过 Jib ,Java 开发者可以使用他们熟悉的 Java 工具来构建容器 。Jib 是一个快速而简单

概念

Google Jib 容器化构建工具

Jibgoogle开源的Java容器化工具,可以直接构建 Java 应用 Docker 和 OCI 镜像的类库,以 Maven 和 Gradle 插件形式提供。

通过 Jib,Java 开发者可以使用他们熟悉的 Java 工具来构建容器。Jib 是一个快速而简单的容器镜像构建工具,它负责处理将应用程序打包到容器镜像中所需的所有步骤。它不需要你编写 Dockerfile 或安装 Docker,而且可以直接集成到 Maven 和 Gradle中—— 只需要将插件添加到构建中,就可以立即将 Java 应用程序容器化

Docker 构建流程
在这里插入图片描述

Jib 构建流程
在这里插入图片描述

简单——Jib使用Java开发,并作为Maven或Gradle的一部分运行。你不需要编写Dockerfile或运行Docker守护进程,甚至无需创建包含所有依赖的大JAR包。因为Jib与Java构建过程紧密集成,所以它可以访问到打包应用程序所需的所有信息。在后续的容器构建期间,它将自动选择Java构建过的任何变体。

快速——Jib利用镜像分层注册表缓存实现快速、增量的构建。它读取你的构建配置,将你的应用程序组织到不同的层(依赖项、资源、类)中,并只重新构建和推送发生变更的层。在项目进行快速迭代时,Jib只将发生变更的层(而不是整个应用程序)推送到注册表来节省宝贵的构建时间

可重现——Jib支持根据Maven和Gradle的构建元数据进行声明式的容器镜像构建,因此,只要输入保持不变,就可以通过配置重复创建相同的镜像

简化

快速 — 快速部署您的更改。Jib 将你的应用程序分成多个层,从类中分离依赖项。你不必等待 Docker 重建整个 Java 应用程序 —— 只需部署更改的层即可

可重现 — 使用相同内容重建容器镜像

Daemonless — 减少 CLI 依赖性。从 MavenGradle 中构建 Docker 镜像,然后推送到你选择的任何注册表,无需编写 Dockerfiles 并调用 docker build/push

下图为某微服务开启 Jib 构建后在 Jenkins 中的构建过程,可以看出构建速度的提升主要在 package 和 push 阶段
在这里插入图片描述

原理

假设我们有一个项目,其组织结构如下:

parentPro
    |-- moduleA
    |-- moduleB
    |-- rest    [rest 模块为 spring boot 启动入口,并依赖 moduleA、moduleB]

对于 SpringBoot 项目,Maven 的默认构建工具Spring-boot-maven-plugin,构建出产物为 Fat JarFat 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 所构建出的镜像相同
在这里插入图片描述

使用

关键几步

配置 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 仓库时需要鉴权
在这里插入图片描述
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
在这里插入图片描述

解决-配置文件

使用命令行方式每次执行都要输入那么长一串命令,这样实在是不方便。另一种方法是在 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>admin@jitwxs-inc.com</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 中标签含义

查看百度网盘
在这里插入图片描述

知秋君
上一篇 2024-08-29 19:02
下一篇 2024-08-29 18:36

相关推荐