Docker+Jenkins+GitLab+Maven+SpringBoot&SpringCloud实现自动化构建镜像与部署详解

1、前言与初衷

  • 本文章会涉及Docker常见命令基础知识点结合不同场景实操一起使用。

  • 本文章会涉及结合工作过程中部署不同环境服务器的项目案例场景为初心进行实际细讲。

  • 本文章主要讲述Docker、Jenkins、GitLab、Git、JDK、SpringBoot、Maven等技术结合实现自动化运维部署(DevOps)应用工程,适合SpringCloud部署。

  • 初衷想法:在学习过程中遇到比较有趣的问题、然而花了点心血和时间去整理,然而进行梳理出来一份文章比较完整有知识体系的DevOps自动化构建与部署工程文章,技术知识内容比较多,而且文章内容较长,然而分了几个章程来讲述。

2、什么是DevOps?

  • DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合,它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

  • 它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作。

3 涉及软件环境搭建内容

特别说明
软件名称 软件版本
CentOS-7-x86_64-Minimal-1810.iso CentOS-7
Docker Version:18.09.6

1、如何使用Maven结合Docker把SpringBoot应用编译成可用的镜像进行部署。
2、其中JDK和Maven是传统方式进行安装,由于本人Centos操作系统是有其他软件依赖它们,有时候传统方式安装软件会更好,这里不过多的阐述。有些软件在Docker安装过程与使用过程并没传统方式的简单,比如:Jenkins

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

4.1 工程结构

  • 打开IDEA或Eclipse新建一个SpringBoot的应用.
环境 说明
env 表示环境变量文件
dev 表示开发环境
test 表示测试环境
  • SpringBoot.png

环境配置特别说明

注意事项:其中Gitlab、Registry、Jenkins都安装在node1机器上面,也就是node1作为主机(master),node2作为slave(从机或副机),机器名起有意义或能区分即可,推荐起master和slave,这里就不作过多的阐述,为了避免看文章有疑问,请看清单列表.

机器名称 IP 内存 处理器 硬盘
node1(master) 192.168.1.235 3G 1核 20G
node2(slave) 192.168.1.236 3G 1核 20G

4.2、SpringBoot配置和代码详解

4.2.1工程的pom.xml配置
  • SpringBoot和Docker依赖的jar配置
<dependencies>
<!-- Springboot依赖的Jar包 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Springboot热部署jar-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

<!--yml配置文件提示插件-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

<!-- spring-boot测试jar -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

    </dependencies>
    <build>
        <finalName>springboot</finalName>
        <!-- 一定要声明如下配置 打包xml 到Jar包 -->
        <!-- <resources>
            <resource>
                <directory>src/main/java</directory>
                是否替换资源中的属性
                <filtering>false</filtering>
            </resource>
        </resources>
        <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
         -->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- 默认支持jdk1.8编译 -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
<!--docke rmaven编译插件-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.12</version>
                <configuration>
                    <dockerDirectory>${project.basedir}</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
             <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.flong.SpringbootApplication</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin> 
        </plugins>
</build>
4.2.2 no main manifest attribute错误解决
  • 配置工程主入口
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
          <mainClass>com.flong.SpringbootApplication</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin> 
4.2.3 env环境变量文件
  • 用于设置环境动态参数,文件是以.env为格式
JAVA_OPTS_DEFAULT=-Xmx512m
4.2.4 Dockerfile打包工程镜像细讲
  • 以开发环境的Dockerfile为例,如果是测试环境则,把所有路径包含springboot_dev改成springboot_test
FROM frolvlad/alpine-oraclejdk8:slim
MAINTAINER jilongliang@sina.com
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN mkdir -p /home/devsoft/springboot_dev
WORKDIR /home/devsoft/springboot_dev
EXPOSE 7011
ADD ./target/springboot.jar ./
CMD java ${JAVA_OPTS_DEFAULT} -Djava.security.egd=file:/dev/./urandom -jar springboot.jar
  • 参数说明

  • 参数.png
  • WORKDIR 工作目录说明进入容器此时会有一个.jar是在Dockerfile的ADD添加进去

docker exec -it 容器名称或容器id /bin/sh 
或要使用sh和bash要看COMMAND,-it
docker exec -it 容器名称或容器id/bin/bash
  • exec .png
4.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)强制指定文件进行运行

#!/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 操作 ......."
    # 清理虚悬镜像,释放磁盘空间
    #docker images|grep none|awk '{print $3 }'|xargs docker rmi

    # 获取容器ID
    CONTAINER_ID=`docker ps -a | grep $IMG_NAME | awk '{ print $1 }'`

    # 获取镜像ID
    IMAGE_ID=`docker images | grep $IMG_NAME | awk '{ print $3 }'`

    # 判断是否存在删除开发容器
    if [[ "$CONTAINER_ID" != "" ]]; then
        docker rm -f $CONTAINER_ID
    fi

    # 判断是否存在删除开发镜像
    if [[ "$IMAGE_ID" != "" ]]; then
        docker rmi -f $IMAGE_ID
    fi
    # $IMG_NAME:$IMG_VERSION 这个IMG_VERSION版本(tag)参数不指定默认latest,通过不同参数执行不同环境文件
    # -f 表示强制指定Dockerfile文件进行编译
    
    echo " .......进入Building & Images 操作 ....... "
    
    #方法1、指定不同文件存放默认的Dockerfile,使用-f进行强制编译
    #docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"$RUN_EVN/Dockerfile $IMG_PATH
    
    #方法2、跟据不同Dockerfile文件的后缀进行编译不同环境的文件
    docker build -t $IMG_NAME:$IMG_VERSION -f $IMG_PATH"env/"Dockerfile_$RUN_EVN $IMG_PATH
    
    
    # 将镜像打一下标签,然后安照标签进行推送到私服里面,标签名就以服务名即可
    docker tag $IMG_NAME:$IMG_VERSION $REGISTRY_URL/$IMG_NAME:$IMG_VERSION
    
    # 推镜像到私服里面
    docker push $REGISTRY_URL/$IMG_NAME:$IMG_VERSION
    
    # 判断是否存在文件夹
    if [ -d "$IMG_PATH" ];then
         echo "已经存在:"$IMG_PATH
    else
        mkdir -p $IMG_PATH
    fi

    # 保存编译之后镜像文件存放到指定路径
    docker save $IMG_NAME -o $IMG_TAR_GZ_PATH/$IMG_NAME.tar.gz
    
    echo " .......进入Runing操作 ....."
    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

    echo " .......Build & Run Finish Success~...."
else
    echo " .......Illegal Command Operation ......."
fi
4.2.6 Docker (save、load、tag、push,pull)命令使用
  • 其中push,pull一个是推,一个是拉,在某种程度下,都是对在私服上面的镜像进行操作

  • docker save命令是保存编译的tar.gz或tar压缩文件,语法如:

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

    参数.png

  • docker tag和docker push命令是一起结合使用,先tag后push,每个镜像名和版本是以冒号区分,而docker pull根据情况使用.
# 将镜像打一下标签,然后安照标签进行推送到私服里面,标签名就以服务名即可
docker tag 镜像名:版本号 私服路径/镜像名:版本号
# 推镜像到私服里面
docker push私服路径/镜像名:版本号
  • 查看镜像

  • 查看镜像.png
  • 浏览器验证docker push推送上私服的镜像

docker push推送.png
push.png
4.2.7 虚悬镜像
  • 在docker编译不成功会或者是新版本覆盖旧版本归类为虚悬镜像,生成这个个镜像既没有仓库名,也没有标签,均为 <none>。一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的。
    虚悬镜像.png
4.2.8 不同环境的配置文件
  • 配置参数
配置文件 配置文件
application.yml 默认配置文件
application-dev.yml 开发配置文件
application-test.yml 测试配置文件
  • 不同环境配置参数内容
server:
  port: 7011
runEvn: '开发环境'
server:
  port: 7011
runEvn: '测试环境'
4.2.9 Controller测试代码
@RestController
public class SimpleController {
   //读取配置动态参数
    @Value("${runEvn}")
    private String runEvn;
    
    @GetMapping("/test")
    public String test() {
        return "this spring boot " + runEvn +" date long " 
       + System.currentTimeMillis();
    }
}

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

5.1 特别说明

  • 以开发环境为例子进行说明

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

5.2 新建maven工程

  • 点击Jenkins的新建任务菜单


    新建maven.png

5.3 参数化构建过程说明

5.3.1添加参数
参数.png
5.3.2 参数说明以开发环境为案例
参数名称 参数值 参数描述
appName springboot 项目名称
server 机器ip地址 服务地址
version 0.0.1 版本号,可以根据情况定义
serverPath /home/jenkins/workspace/springboot_dev/ 远程存放代码的路径或者说是远程的文件目录
port 7011 端口
env dev 发布的环境;dev 联调环境,test 测试环境,pre 预发布环境,fix 修复环境,prod 生产环境
  • 为了手机像素问题提供图片
  • image.png
5.3.3 源码管理
  • 源码管理.png
5.3.4 Build编译设置
  • image.png
  • 表示忽略测试单元类进行编译
clean install -U -Dmaven.test.skip=true

5.4 SSH Publishers设置

  • 其中SSH Server Name就是在http://jenkins地址:端口/jenkins/configure设置好进行选择

  • Transfer Set Source file传输文件的路径,可以使用参数构建的占位符${serverPath}获取

  • Remote directory远程文件目录,同理也参数构建的占位符${serverPath}获取

SSH .png
  • SSH Publishers shell脚本#!/bin/bash表示告诉终端使用bash解析器进行执行,而且只有第一行bash才有效
#!/bin/bash
# 创建目录
mkdir -p ${serverPath}
# 切换目录
cd ${serverPath}
# 运行脚本
sh build.sh  $server  ${appName}  ${version}  ${port} ${env} ${serverPath}

5.5 构建与编译部署项目

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

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

  • 构建过程

  • 构建.png
  • 部署结果

部署结果.png

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

6.1 特别说明

  • 以测试环境为例子进行说明

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

6.2 新建maven工程

  • 点击Jenkins的新建任务菜单


    新建maven.png

6.3 参数化构建过程说明

6.3.1添加参数
参数.png
6.3.2 参数说明以测试环境为案例
参数名称 参数值 参数描述
appName springboot 项目名称
server 机器ip地址 服务地址
version 0.0.1 版本号,可以根据情况定义
serverPath /home/jenkins/workspace/springboot_test/ 远程存放代码的路径或者说是远程的文件目录
port 7011 端口
env test 发布的环境;dev 联调环境,test 测试环境,pre 预发布环境,fix 修复环境,prod 生产环境
targetServerPath /home/jenkins/workspace/ 目标服务器文件路径
  • 为了手机像素问题提供图片
  • 参数.png
6.3.3 源码管理
  • 源码管理.png
6.3.4 Build编译设置
  • image.png
  • 表示忽略测试单元类进行编译
clean install -U -Dmaven.test.skip=true

6.4 SSH Publishers设置

  • 其中SSH Server Name就是在http://jenkins地址:端口/jenkins/configure设置好进行选择

  • Transfer Set Source file传输文件的路径,可以使用参数构建的占位符${serverPath}获取

  • Remote directory远程文件目录,同理也参数构建的占位符${serverPath}获取

  • docker_server1表示与Jenkins部署同一个宿主机,使用脚本有远程机器shell脚本操作免登陆操作。

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

#!/bin/bash
#  打印信息
echo "用户名${userName}"
echo "服务器${server}"
echo "服务器目录${serverPath}"
#  远程创建存放远程上传的代码目录路径
ssh $server  mkdir -p ${targetServerPath}
#  远程拷贝代码到目标机器指定路径
scp -r ${serverPath}/  ${userName}@${server}:${targetServerPath}

*docker_server2表示要部署那台目标机器,所以它的脚本跟docker_server1不一样.

  • docker_server2.png
  • docker_server2 Shell脚本

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

6.5 构建与编译部署项目

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

6.6 构建&运行&部署结果

  • 构建过程
构建过程
  • 部署结果


    部署结果.png

备注:部署操作动态图片


部署操作动态图片.gif

部署操作动态图片.gif
文档.gif

最全的Docker+Jenkins+GitLab+Maven+SpringBoot&SpringCloud实现自动化构建镜像与部署&源代码详细教程文档 在GitHub base代码分支里面
欢迎下载,同时欢迎高手指点不知足的地方,感恩


7、总结&建议&学习

7.1总结与建议

  • 1、此文章仅供提供参考学习指引,如需要系统得学习可以根据自身找资料去学习。

  • 2、以上问题都是根据个人实际学习过程中遇到的问题进行一个一个问题进行梳理与总结整理,除了技术问题查很多网上资料通过进行学习之后整理与分享。

  • 3、在学习过程中也遇到很多困难和疑点,如有问题或误点,望各位老司机多多指出或者提出建议。本人会采纳各种好建议和正确方式不断完善现况,人在成长过程中的需要优质的养料。

  • 4、当遇到问题的时候建议多问『谷歌 、必应、stackoverflow、度娘』这些大神。

  • 5、建议看官方手册更权威,由于随着技术的发展与迭代,通常官方的文档更新较快,国内的网站资料更新较慢。

  • 6、计算机是一门『做中学』的学科,不是会了再去做,而是做了才会。多练,常言道熟能生巧。

  • 7、建议学什么技术『先Know how,再Know Why』,意思就说先入门,搞一个HelloWorld,再深究的意思。

  • 8、希望此文章能帮助你更好了解什么(DevOps)是自动化构建镜像与部署,如何在Docker+Jenkins+GitLab+Maven+SpringBoot&SpringCloud自动构建镜像与部署服务应用,整个学习流程与搭建会有点小曲折,并不会那么顺利,也希望你看了此文章或者通过找资料进行亲身经历学习效果会更好,此文章属于原创,欢迎转载和收藏

7.2 学习&参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容