Java SpringCloud Docker Jenkins GitLab Maven

1、前言与初衷

本文章会涉及Docker常见命令基础知识点结合不同场景实操一起使用。
本文章会涉及结合工作过程中部署不同环境服务器的项目案例场景为初心进行实际细讲。
本文章主要讲述Docker、Jenkins、GitLab、Git、JDK、SpringBoot、Maven等技术结合实现自动化运维部署(DevOps)应用工程,适合SpringCloud部署。
初衷想法:在学习过程中遇到比较有趣的问题、然而花了点心血和时间去整理,然而进行梳理出来一份文章比较完整有知识体系的DevOps自动化构建与部署工程文章,技术知识内容比较多,而且文章内容较长,然而分了几个章程来讲述

2、什么是DevOps?

DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合,它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作。
特别说明
SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图1
1、如何使用Maven结合Docker把SpringBoot应用编译成可用的镜像进行部署。
2、其中JDK和Maven是传统方式进行安装,由于本人Centos操作系统是有其他软件依赖它们,有时候传统方式安装软件会更好,这里不过多的阐述。有些软件在Docker安装过程与使用过程并没传统方式的简单,比如:Jenkins。

3、需要准备的工作有哪些

3.1 工程结构

  • 打开IDEA或Eclipse新建一个SpringBoot的应用.

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图2
SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图3
环境配置特别说明 :::tips 注意事项:其中Gitlab、Registry、Jenkins都安装在node1机器上面,也就是node1作为主机(master),node2作为slave(从机或副机),机器名起有意义或能区分即可,推荐起master和slave,这里就不作过多的阐述,为了避免看文章有疑问,请看清单列表. ::: SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图4

3.2、SpringBoot配置和代码详解

3.2.1 工程的pom.xml配置

  • SpringBoot和Docker依赖的jar配置 ```xml

    org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-configuration-processor true org.springframework.boot spring-boot-starter-test test

springboot org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 org.springframework.boot spring-boot-maven-plugin repackage com.spotify docker-maven-plugin 0.4.12 ${project.basedir} / ${project.build.directory} ${project.build.finalName}.jar org.apache.maven.plugins maven-jar-plugin com.flong.SpringbootApplication

  1. <a name="JAmgN"></a>
  2. #### 3.2.2 no main manifest attribute错误解决
  3. - 配置工程主入口
  4. ```xml
  5. <plugin>
  6. <groupId>org.apache.maven.plugins</groupId>
  7. <artifactId>maven-jar-plugin</artifactId>
  8. <configuration>
  9. <archive>
  10. <manifest>
  11. <mainClass>com.flong.SpringbootApplication</mainClass>
  12. </manifest>
  13. </archive>
  14. </configuration>
  15. </plugin>

3.2.3 env环境变量文件

  • 用于设置环境动态参数,文件是以.env为格式

JAVA_OPTS_DEFAULT=-Xmx512m

3.2.4 Dockerfile打包工程镜像细讲

  • 以开发环境的Dockerfile为例,如果是测试环境则,把所有路径包含springboot_dev改成springboot_test

    1. FROM frolvlad/alpine-oraclejdk8:slim
    2. MAINTAINER jilongliang@sina.com
    3. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    4. RUN mkdir -p /home/devsoft/springboot_dev
    5. WORKDIR /home/devsoft/springboot_dev
    6. EXPOSE 7011
    7. ADD ./target/springboot.jar ./
    8. CMD java ${JAVA_OPTS_DEFAULT} -Djava.security.egd=file:/dev/./urandom -jar springboot.jar
  • 参数说明

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图5

  • WORKDIR 工作目录说明进入容器此时会有一个.jar是在Dockerfile的ADD添加进去
    1. docker exec -it 容器名称或容器id /bin/sh
    或要使用sh和bash要看COMMAND,-it
    1. docker exec -it 容器名称或容器id/bin/bash
    SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图6

    3.2.5 build.sh文件shell脚本详解

    注意点1:经过测试动态变量的【等号】不能有空格和tab键置位,否则获取不了值,而且在shell脚本代码里面不支持空格格式化,支持tab置位格式化。在终端(ssh软件端)或Jenkins客户端shell命令,『位置变量』的参数以空格隔开。
    如:sh build.sh 192.168.1.235 springboot 0.0.1 7011 /home/jenkins/workspace/springboot_dev
    $IMG_NAME:$IMG_VERSION这个IMG_VERSION版本(tag)参数不指定默认latest
    注意点2:通常情况下Docker是默认执行Dockerfile,但是可以自定义后缀文件进行编译,前提必须要-f(force)强制指定文件进行运行 ```bash

    !/usr/bin/env bash

    动态变量的【等号】不能有空格和tab键置位,否则获取不了值,而且在shell脚本代码里面不支持空格格式化,支持tab置位格式化。

    在终端(ssh软件端)或Jenkins客户端shell命令,参数以空格隔开。如:sh build.sh 192.168.1.235 springboot 0.0.1 7011 /home/jenkins/workspace/springboot_dev

    IMG_SERVER=”$1” IMG_NAME=”$2” IMG_VERSION=”$3” IMG_PORT=”$4” RUN_EVN=”$5” IMG_PATH=”$6”

echo “服务地址:$IMG_SERVER” echo “工程镜像名称:$IMG_NAME” echo “工程版本号:$IMG_VERSION” echo “工程端口:$IMG_PORT” echo “服务环境:$RUN_EVN”

私服访问url路径和编译之后镜像文件存放到指定路径固定,不动态参数进行处理传值.

REGISTRY_URL=”192.168.1.235:5000” IMG_TAR_GZ_PATH=”/home/img_tar_gz_path/“

判断动态参数不为空字符串的时候才执行下面操作

if [ “$IMG_SERVER” != “” ] && [ “$IMG_NAME” != “” ] && [ “$IMG_VERSION” != “” ] && [ “$IMG_PORT” != “” ]; then

echo “ …….进入删除 Container & Images 操作 …….”

  1. # 清理虚悬镜像,释放磁盘空间
  2. #docker images|grep none|awk '{print $3 }'|xargs docker rmi
  3. # 获取容器ID
  4. CONTAINER_ID=`docker ps -a | grep $IMG_NAME | awk '{ print $1 }'`
  5. # 获取镜像ID
  6. IMAGE_ID=`docker images | grep $IMG_NAME | awk '{ print $3 }'`
  7. # 判断是否存在删除开发容器
  8. if [[ "$CONTAINER_ID" != "" ]]; then
  9. docker rm -f $CONTAINER_ID
  10. fi
  11. # 判断是否存在删除开发镜像
  12. if [[ "$IMAGE_ID" != "" ]]; then
  13. docker rmi -f $IMAGE_ID
  14. fi
  15. # $IMG_NAME:$IMG_VERSION 这个IMG_VERSION版本(tag)参数不指定默认latest,通过不同参数执行不同环境文件
  16. # -f 表示强制指定Dockerfile文件进行编译
  17. echo " .......进入Building & Images 操作 ....... "
  18. #方法1、指定不同文件存放默认的Dockerfile,使用-f进行强制编译
  19. #docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"$RUN_EVN/Dockerfile $IMG_PATH
  20. #方法2、跟据不同Dockerfile文件的后缀进行编译不同环境的文件
  21. docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"Dockerfile_$RUN_EVN $IMG_PATH
  22. # 将镜像打一下标签,然后安照标签进行推送到私服里面,标签名就以服务名即可
  23. docker tag $IMG_NAME:$IMG_VERSION $REGISTRY_URL/$IMG_NAME:$IMG_VERSION
  24. # 推镜像到私服里面
  25. docker push $REGISTRY_URL/$IMG_NAME:$IMG_VERSION
  26. # 判断是否存在文件夹
  27. if [ -d "$IMG_PATH" ];then
  28. echo "已经存在:"$IMG_PATH
  29. else
  30. mkdir -p $IMG_PATH
  31. fi
  32. # 保存编译之后镜像文件存放到指定路径
  33. docker save $IMG_NAME -o $IMG_TAR_GZ_PATH/$IMG_NAME.tar.gz
  34. echo " .......进入Runing操作 ....."
  35. docker run -d --network default_network --restart=always --env-file=./.env -e spring.profiles.active=$RUN_EVN --expose=$IMG_PORT --name=$IMG_NAME -p $IMG_PORT:$IMG_PORT $IMG_NAME:$IMG_VERSION
  36. echo " .......Build & Run Finish Success~...."

else echo “ …….Illegal Command Operation …….” fi

  1. <a name="TfuDv"></a>
  2. #### 3.2.6 Docker (save、load、tag、push,pull)命令使用
  3. - 其中push,pull一个是推,一个是拉,在某种程度下,都是对在私服上面的镜像进行操作
  4. - docker save命令是保存编译的tar.gz或tar压缩文件,语法如:
  5. ```bash
  6. docker save 镜像名 -o 路径/镜像名.tar.gz

  1. docker save 镜像名 -o 路径/镜像名.tar

docker load 命令是用于导入使用 docker save 命令导出的镜像,此命令非常重要,由于有些客户要求项目工程要求部署在内网,此时这个命令在无网络的内网情况下部署项目的时候就体现它重要的地位了.语法 docker load [OPTIONS],在加载的过程有点慢,因为文件有点大,其中显示Loady Layer [======]输出信息,证实镜像是分层关系。

  1. docker load -i /home/img_tar_gz_path/springboot.tar.gz

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图7

  • 参数说明

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图8

  • docker tagdocker push命令是一起结合使用,先tag后push,每个镜像名和版本是以冒号区分,而docker pull根据情况使用。

    1. # 将镜像打一下标签,然后安照标签进行推送到私服里面,标签名就以服务名即可
    2. docker tag 镜像名:版本号 私服路径/镜像名:版本号
    3. # 推镜像到私服里面
    4. docker push私服路径/镜像名:版本号
  • 查看镜像

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图9
浏览器验证docker push推送上私服的镜像
SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图10
SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图11

3.2.7 虚悬镜像

  • 在docker编译不成功会或者是新版本覆盖旧版本归类为虚悬镜像,生成这个个镜像既没有仓库名,也没有标签,均为 。一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的。

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图12

3.2.8 不同环境的配置文件

配置参数
SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图13
不同环境配置参数内容

  1. server:
  2. port: 7011
  3. runEvn: '开发环境'
  4. server:
  5. port: 7011
  6. runEvn: '测试环境'

3.2.9 Controller测试代码

  1. @RestController
  2. public class SimpleController {
  3. //读取配置动态参数
  4. @Value("${runEvn}")
  5. private String runEvn;
  6. @GetMapping("/test")
  7. public String test() {
  8. return "this spring boot " + runEvn +" date long "
  9. + System.currentTimeMillis();
  10. }
  11. }

4、非多台机器免密远程登录&Jenkins部署详解

4.1 特别说明

  • 以开发环境为例子进行说明
  • 开发环境部署目标机器是与Jenkins机器同一台机器,一般情况,Jenkins是单独一台机器,这里为了节省自身电脑内存,故放在同一台机器进行演示与学习。

    4.2 新建maven工程

  • 点击Jenkins的新建任务菜单

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图14

4.3 参数化构建过程说明

4.3.1 添加参数

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图15

4.3.2 参数说明以开发环境为案例

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图16

4.3.3 源码管理

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图17

4.3.4 Build编译设置

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图18
表示忽略测试单元类进行编译

  1. clean install -U -Dmaven.test.skip=true

4.4 SSH Publishers设置

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图19

  • SSH Publishers shell脚本#!/bin/bash表示告诉终端使用bash解析器进行执行,而且只有第一行bash才有效。

    1. #!/bin/bash
    2. # 创建目录
    3. mkdir -p ${serverPath}
    4. # 切换目录
    5. cd ${serverPath}
    6. # 运行脚本
    7. sh build.sh $server ${appName} ${version} ${port} ${env} ${serverPath}

    4.5 构建与编译部署项目

  • 截图的构建参数都是在参数化构建过程配置的参数

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图20

4.6 构建&运行&&部署结果

  • 构建过程

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图21

  • 部署结果

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图22

5、多台机器免密远程登录&Jenkins部署流程详解

5.1 特别说明

  • 以测试环境为例子进行说明
  • 步骤流程几乎一样,唯一是在SSH Publishers 和源码存放路径不一样,测试环境部署目标机器是与Jenkins机器不同一台机器

    5.2 新建maven工程

  • 点击Jenkins的新建任务菜单

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图23

5.3 参数化构建过程说明

5.3.1 添加参数

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图24

5.3.2 参数说明以测试环境为案例

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图25

5.3.3 源码管理

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图26

5.3.4 Build编译设置

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图27

5.4 SSH Publishers设置

  1. 其中SSH Server Name就是在http://jenkins地址:端口/jenkins/configure设置好进行选择
  2. Transfer Set Source file传输文件的路径,可以使用参数构建的占位符${serverPath}获取
  3. Remote directory远程文件目录,同理也参数构建的占位符${serverPath}获取
  4. docker_server1表示与Jenkins部署同一个宿主机,使用脚本有远程机器shell脚本操作免登陆操作。

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图28

  • docker_server1 Shell脚本#!/bin/bash表示告诉终端使用bash解析器进行执行,而且只有第一行bash才有效。

    1. #!/bin/bash
    2. # 打印信息
    3. echo "用户名${userName}"
    4. echo "服务器${server}"
    5. echo "服务器目录${serverPath}"
    6. # 远程创建存放远程上传的代码目录路径
    7. ssh $server mkdir -p ${targetServerPath}
    8. # 远程拷贝代码到目标机器指定路径
    9. scp -r ${serverPath}/ ${userName}@${server}:${targetServerPath}
  • docker_server2表示要部署那台目标机器,所以它的脚本跟docker_server1不一样.

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图29

  • docker_server2 Shell脚本

    1. #!/bin/bash
    2. # 切换文件目录
    3. cd ${serverPath}
    4. # 执行脚本
    5. sh build.sh ${server} ${appName} ${version} ${port} ${env} ${serverPath}

    5.5 构建与编译部署项目

  • 截图的构建参数都是在参数化构建过程配置的参数

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图30

5.6 构建&运行&部署结果

  • 构建过程

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图31

  • 部署结果

SpringCloud Docker Jenkins GitLab Maven实现自动化构建与部署实战 - 图32