• 【微服务部署】三、Jenkins+Maven插件Jib一键打包部署SpringBoot应用Docker镜像步骤详解


      前面我们介绍了K8S+Docker+Maven插件打包部署SpringCloud微服务项目,在实际应用过程中,很多项目没有用到K8S和微服务,但是用到了Docker和SpringBoot,所以,我们这边介绍,如果使用Jenkins+jib-maven-plugin插件打包部署SpringBoot项目的Docker镜像。
      网上有多种Docker打包插件使用说明,讲解最多的是Spotify开源的,Spotify官方已不再推荐使用docker-maven-plugin插件进行打包,而是推荐其最新的docker打包插件dockerfile-maven-plugin,但是dockerfile-maven-plugin也已经很久没有更新了,在使用方面也有局限性,比如:只支持在本机Docker的镜像build、tag、push。
      经过几个插件的对比,发现Google开源的Jib插件功能更强大,它可以不写Dockerfile,不需要在本地安装Docker环境就能实现Docker打包,而且一直在更新,所以这里选择这个插件作为我们的Docker打包插件。
      Jib构建Java的Docker和OCI映像,不需要在本机安装Docker daemon,也不需要深入掌握Docker最佳实践。它可以作为Maven和Gradle的插件以及Java库使用。
      下面介绍Jib( jib-maven-plugin插件 )如何将SpringBoot应用程序分层打包Docker镜像,充分利用Docker的镜像分层复用机制,解决网络限制和占用大量磁盘空间的问题。
    Jib( jib-maven-plugin插件 )构建的三个参数:

    • buildTar:本地构建,不需要Docker daemon就可以将镜像生成tar文件,保存在工程的target目录下
    • dockerBuild:将构建的镜像存到当前环境的Docker daemon
    • build:将构建的镜像推送到远程仓库,官方仓库或者Harbor私有仓库
    一、SpringBoot项目jib-maven-plugin插件配置说明

      我们这里主要使用buildTar命令,将Docker镜像文件打包在本地,然后通过Jenkins插件发布到服务器运行,这样可以不需要搭建使用私有Docker镜像仓库Harbor。

    • 打包命令:
      -Dimage可以在打包时自定义镜像名称和版本,这个可以在Jenkins脚本时使用,如果不配置默认使用pom.xml里面配置的镜像名称和版本,如果不设置版本,默认版本是latest
    clean package -Ptest -Dimage=gitegg:1.0.1 jib:buildTar -f pom.xml
    
    • 1
    • docker镜像载入命令
      docker load用来载入镜像包,但是不能对载入的镜像重命名;docker import用来载入容器包,但两者都会恢复为镜像,可以为镜像指定新名称;经过测试,jib-maven-plugin插件生成的Docker镜像文件jib-image.tar只能通过docker load载入,并且在pom.xml配置中format不能选择OCI(K8S时使用OCI),否则载入不了。
    docker load --input  jib-image.tar
    
    • 1
    • 可以将jib-maven-plugin插件的打包命令绑定到Maven的生命周期
                        
                            
                                install
                                
                                    build
                                
                            
                        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 将Docker镜像推送到私有镜像仓库Harbor,当然这里不需要,但是可以配置镜像名称和镜像版本,当在运行打包命令时,没有加参数-Dimage,就会取此处的配置
                            
                                私有仓库地址/项目名称/${project.artifactId}:${project.version}
                                
                                    私有仓库用户名
                                    私有仓库密码
                                
                            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • volumes 创建容器内的目录,当SpringBoot项目记录日志等需要自定义的目录地址时,此处需要定义容器内的目录;SpringBoot使用的内嵌Tomcat容器默认使用/tmp作为工作目录,这里可以不配置/tmp的valumes。
                                
                                
                                    /tmp
                                    /log
                                
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • workingDirectory 容器内的工作目录,容器启动时执行的命令会在容器内的此目录下执行。
    /gitegg
    
    • 1
    • format 使用OCI构建OCI容器映像。这里直接注释掉不要使用,否则docker load时不能载入,在K8S里面可以使用,所以这里不使用这个format。
     
    OCI
    
    • 1
    • 2

    下面是SpringBoot项目中pom.xml的jib-maven-plugin插件配置信息:

    ······
        
    ······
            
            3.3.2
    ······
        
    ······
                    
                    
                        com.google.cloud.tools
                        jib-maven-plugin
                        ${jib.maven.plugin.version}
                        
                        
                            
                                install
                                
                                    build
                                
                            
                        
                        
                            
                            true
                            
                            
                                openjdk:11-jre
                            
                            
                                ${docker.harbor.addr}/${docker.harbor.project}/${project.artifactId}:${project.version}
                                
                                    ${docker.harbor.username}
                                    ${docker.harbor.password}
                                
                            
                            
                                
                                
                                    -Xms512m
                                    -Xmx8g
                                
                                
                                
                                    /tmp
                                    /log
                                
                                /gitegg
                                
                                    Asia/Shanghai
                                
                                
                                USE_CURRENT_TIMESTAMP
                                
    
                            
                        
                    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    二、服务器Docker运行环境配置

      前面我们讲了如何安装Docker,以及相关配置,所以这里不再赘述,直接按照自己的服务器实际情况进行安装配置Docker即可,这里讲解如何为运行SpringBoot的Fat Jar做环境准备,以及说明镜像包传输到服务器之后执行的部署脚本。

    1. 部署及备份目录准备
    • 新建 /opt/tmp 目录,用于Jenkins打包后,通过 Publish Over SSH插件将包传输到服务器的临时目录。
    • 新建 /opt/bak 目录,用于存储所有部署过的包备份,方便后续版本回滚。此目录可能会占用很大空间,所以需要选择一个磁盘空间大的挂载目录。
    • 新建 /opt/script 目录,用于Jenkins将包传输完成之后,执行安装、备份操作的相关命令脚本。
    • 新建 /data/container/docker_server/tmp 目录,用于映射容器内/tmp目录,/tmp目录是SpringBoot内置Tomcat默认运行目录。
    • 新建 /data/container/docker_server/logs目录,用于映射容器内/var/log目录,/var/log目录是项目配置的日志存放目录,映射到宿主机之后,方便查看不同级别的日志。
    mkdir -p /opt/tmp /opt/bak /opt/script /data/container/docker_server/tmp /data/container/docker_server/logs
    
    chmod -R 777 /opt/tmp /opt/bak /opt/script /data/container/docker_server/tmp /data/container/docker_server/logs
    
    • 1
    • 2
    • 3
    2. 部署脚本编写说明
    • 定义入参,可以通过Jenkins任务将参数传入脚本中,我们定义了下面5个参数:
      container_name=gitegg-server : 容器名称
      image_name=gitegg-server : 镜像名称
      version=latest : 镜像版本
      image_port=8182 : 宿主主机端口映射
      server_port=8080 : 容器内服务端口
    • 对参数进行检查,是否未传入参数,这里根据自己的实际情况判断,比如必须传入哪些参数,就设置参数的个数不能小于几。
    echo "param validate"
    if [ $# -lt 1 ]; then  
      echo "you must use like this : ./publish_docker_server.sh    [image port] [server port]"  
      exit  
    fi 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 入参赋值,如果有参数传入,则取服务参数,如果没有参数传入则取默认值
    if [ "$1" != "" ]; then
       container_name="$1"
    fi
    echo "container_name=" $container_name
    if [ "$2" != "" ]; then
       image_name="$2"
    fi
    if [ "$3" != "" ]; then
       version="$3"
    fi
    echo "version=" $version
    if [ "$4" != "" ]; then
       image_port="$4"
    fi
    echo "image_port=" $image_port
    if [ "$5" != "" ]; then
       server_port="$5"
    fi
    echo "server_port=" $server_port
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 停止并删除容器
    echo "执行docker ps"
    docker ps 
    if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]]; 
    then 
      echo $container_name "容器存在,停止并删除"
      echo "docker stop" $container_name
      docker stop $container_name
      echo "docker rm" $container_name
      docker rm $container_name
    else 
      echo $container_name "容器不存在"
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 停止并删除镜像
    # 删除镜像
    echo "执行docker images"
    docker images
    if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]]; 
    then 
      echo $image_name '镜像存在,删除镜像'
      docker rmi $(docker images -q $image_name 2> /dev/null) --force
    else 
      echo $image_name '镜像不存在'
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 备份本次安装镜像包
    #bak image
    echo "bak image" $image_name
    BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d`
    mkdir -p "$BAK_DIR"
    cp "/opt/tmp/jib-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 执行安装镜像包命令
    echo "docker load" $image_name
    docker load --input /opt/tmp/jib-image.tar
    
    • 1
    • 2
    • 执行运行命令
    echo "docker run" $image_name
    docker run -d -p $image_port:$server_port --name=$container_name --restart=always -v /data/container/docker_server/tmp:/tmp -v /data/container/docker_server/logs:/var/log $image_name
    
    • 1
    • 2
    • 删除安装文件,因为前面已经备份过了,所以这里将临时安装文件删除
    echo "remove tmp " $image_name
    rm -rf /opt/tmp/jib-image.tar
    
    • 1
    • 2
    • 打印执行完成的命令
    echo "Docker Server is starting,please try to access $container_name conslone url"
    
    • 1
    3. 完整的安装部署脚本
    container_name=gitegg-server
    image_name=gitegg-server
    version=latest
    image_port=8181
    server_port=8080
    echo "param validate"
    if [ $# -lt 1 ]; then  
      echo "you must use like this : ./publish_docker_server.sh    [image port] [server port]"  
      exit  
    fi
    if [ "$1" != "" ]; then
       container_name="$1"
    fi
    echo "container_name=" $container_name
    if [ "$2" != "" ]; then
       image_name="$2"
    fi
    if [ "$3" != "" ]; then
       version="$3"
    fi
    echo "version=" $version
    if [ "$4" != "" ]; then
       image_port="$4"
    fi
    echo "image_port=" $image_port
    if [ "$5" != "" ]; then
       server_port="$5"
    fi
    echo "server_port=" $server_port
    
    echo "执行docker ps"
    docker ps 
    if [[ "$(docker inspect $container_name 2> /dev/null | grep $container_name)" != "" ]]; 
    then 
      echo $container_name "容器存在,停止并删除"
      echo "docker stop" $container_name
      docker stop $container_name
      echo "docker rm" $container_name
      docker rm $container_name
    else 
      echo $container_name "容器不存在"
    fi
    # 删除镜像
    echo "执行docker images"
    docker images
    if [[ "$(docker images -q $image_name 2> /dev/null)" != "" ]]; 
    then 
      echo $image_name '镜像存在,删除镜像'
      docker rmi $(docker images -q $image_name 2> /dev/null) --force
    else 
      echo $image_name '镜像不存在'
    fi
    
    #bak image
    echo "bak image" $image_name
    BAK_DIR=/opt/bak/docker/$image_name/`date +%Y%m%d`
    mkdir -p "$BAK_DIR"
    cp "/opt/tmp/jib-image.tar" "$BAK_DIR"/"$image_name"_`date +%H%M%S`.tar
    
    echo "docker load" $image_name
    docker load --input /opt/tmp/jib-image.tar
    echo "docker run" $image_name
    docker run -d -p $image_port:$server_port --name=$container_name --restart=always -v /data/container/docker_server/tmp:/tmp -v /data/container/docker_server/logs:/var/log $image_name
    echo "remove tmp " $image_name
    rm -rf /opt/tmp/jib-image.tar
    
    echo "Docker Server is starting,please try to access $container_name conslone url"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    三、新建Jenkins配置打包任务,部署SpringBoot项目Docker镜像
    1. Dashboard > 新建任务,输入任务名称,选择“构建一个maven项目”,点击确定。

    Dashboard
    新建任务

    2. 项目配置,进入到任务配置页
    • 丢弃旧的构建 :这里在保持构建的最大个数填写5,当然可以根据自己情况填写,否则旧的构建包会一直存在占用磁盘空间。
      丢弃旧的构建
    • 源码管理:配置git代码地址、用户名密码和版本分支,如果是需要用户名密码的git库,那么下面需要选择访问的用户名密码,这里一定要使用用户名密码方式,使用token的方式无法选中。可以在下方add,也可以在Jenkins全局Credentials 中添加,方便其它任务使用。
      源码管理

    访问凭证

    • 构建触发器:可选可不选,这个根据自己的需求选择,任务在什么情况下出发构建。
      构建触发器
    • 构建环境:这里不需要选择,在介绍构建NodeJS项目时,需要选中NodeJS环境。
      构建环境
    • Build:这里填写Maven打包命令,可以添加参数选择打包环境test或prod,定义镜像名称和版本等。
    clean package -Dmaven.test.skip=true -Ptest -Dimage=gitegg jib:buildTar -f pom.xml
    
    • 1

    Build

    • Post Steps:将打包后的文件发送到服务器,并执行设置好的脚本,这里选择Run only if build succeeds,当构建成功时Post。

    Post Steps1

    • Exec command:将打好的包发布到环境之后,在环境上执行的部署脚本命令。publish_docker_server.sh 是脚本文件、第一个gitegg 是容器名称、第二个gitegg 是镜像名称、latest 是镜像版本、8181 是宿主机端口号、8080 是容器内服务口号。
    /opt/script/publish_docker_server.sh gitegg gitegg latest 8181 8080
    
    • 1

    Post Steps2

    3. 运行构建任务
    • 立即构建
      在这里插入图片描述

    • 查看构建日志:点击立即构建之后,下方会出现进度条,点击进度条就可以进入构建日志界面。
      查看构建日志

    日志

    • 构建成功后,下方会给出构建成功提示,此时登录远程服务器查看文件是否部署成功即可。
      部署成功
    4. Docker镜像部署成功之后,可以使用以下Docker常用命令查看运行情况
    • 查看镜像
    docker images
    
    • 1
    • 查看有哪些容器在运行
    docker ps
    
    • 1
    • 停止容器
    docker stop 容器id
    
    • 1
    • 删除容器、删除镜像
    docker rm 容器id
    docker rmi 镜像id
    
    • 1
    • 2
    • 查看容器运行日志
    docker logs -f 容器id
    
    • 1
    • 进入到容器
    docker exec -it 容器id /bin/bash
    
    • 1
  • 相关阅读:
    VS Code For Web 深入浅出 -- 进程间通信篇
    Unity DOTS系列之Filter Baking Output与Prefab In Baking核心分析
    iOS——UIColor与CGColor与CALayer
    【C++】二叉搜索树
    (最优化理论与方法)第二章最优化所需基础知识-第六节1:凸函数前置基础知识
    lv8 嵌入式开发-网络编程开发 14
    2022 9.13 模拟
    阿里巴巴全球数学竞赛
    ImmunoChemistry艾美捷基本细胞毒性试验试剂盒测定方案
    基于BlockingQueue的异步处理
  • 原文地址:https://blog.csdn.net/wmz1932/article/details/132652299