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)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

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

3 涉及软件环境搭建内容

  • 如何在Centos7安装JDK1.8-u121详解

  • 如何在Centos7安装Maven3.6.1详解

  • 如何在Centos7安装Git详解

  • 如何在CentOS7与Git配置免密码登陆详解

  • 如何在Docker安装GitLab详解

  • 如何在Docker创建NetWork网络详解

  • 如何在Docker安装Registry私服详解

  • 如何在Docker安装Jenkins详解

见附录

特别说明

84a63ff89c25def3f6ba692cea7c6887.png

图片

1、如何使用Maven结合Docker把SpringBoot应用编译成可用的镜像进行部署。

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

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

4.1 工程结构
  • 打开IDEA或Eclipse新建一个SpringBoot的应用.

eddc75ea41bfb8ff9f39785fcb52fd14.png

图片
b68445328330a1c27cdc0a6ecf001af0.png
图片

环境配置特别说明

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

acb020acc8a83272ef2390e15acf26ed.png

图片
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
  • 参数说明

ec2dd639e56db308fff7159952712b28.png

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

docker exec -it 容器名称或容器id /bin/sh

或要使用sh和bash要看COMMAND,-it

docker exec -it 容器名称或容器id/bin/bash

f6b9894551a32aecbefc09016b061267.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

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

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

15636e999c4d88950eb8985644893683.png

图片
  • 参数说明

f112ca8a44898b3faf7b6b3d55336038.png

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

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

451715b826576c164b57246e1f0b7d4c.png
图片

浏览器验证docker push推送上私服的镜像

d0b527af60f59343aa44f502b1c5d542.png

图片

194d5c76195e1e55fc0ef51c5bdca451.png

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

2bd31ce56f78d2b39161207ea7ecac9f.png

图片
4.2.8 不同环境的配置文件

配置参数

9f3471665e14a1977e301ec279dc96e6.png

图片

不同环境配置参数内容

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的新建任务菜单

425bd38ff5f2616d5742af440aef2353.png

图片
5.3 参数化构建过程说明
5.3.1添加参数

4f08090b37a5cb61598ffeb9a237c958.png

图片
5.3.2 参数说明以开发环境为案例

f89c216a74196f82d38fff76a9e121d2.png

图片
5.3.3 源码管理

3fb3568764a1397809f6a31e26bfd3c1.png

图片
5.3.4 Build编译设置

3de14e3ec76c97e766e55c05f3226c46.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}获取

2290a5a82c1b92f150d70126a0a63e1d.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 构建与编译部署项目
  • 截图的构建参数都是在参数化构建过程配置的参数

2ea3b1cd0c26f720c4786ace91a63843.png

图片
5.6 构建&运行&&部署结果
  • 构建过程

4ecfeab04f518af0c9535ada5f99b3d4.png

图片
  • 部署结果

d49b43fafc23aac65400a5d0c5cc66a3.png

图片

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

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

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

6.2 新建maven工程
  • 点击Jenkins的新建任务菜单

5a420db976b747a7cdc5ed76502fe778.png

图片
6.3 参数化构建过程说明
6.3.1添加参数

b5ea16a090b5ba50ff01d441a658a115.png

图片
6.3.2 参数说明以测试环境为案例

97d2efb4c5d9b735b8ce8b66b90748bc.png

图片
6.3.3 源码管理

d3b0657cd37f0729c4014cc5d3baf3e0.png

图片
6.3.4 Build编译设置

dc3f8cf5dca30690ca69ce2a73177d4c.png

图片
6.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脚本操作免登陆操作。

d1c2e6602bf90f2f6ecfb492bae35e0b.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不一样.

aae7a1e3d6c1255c747990a9328da134.png

图片
  • docker_server2 Shell脚本

#!/bin/bash
# 切换文件目录
cd ${serverPath}
# 执行脚本
sh build.sh ${server}  ${appName}  ${version}  ${port}  ${env} ${serverPath}
6.5 构建与编译部署项目
  • 截图的构建参数都是在参数化构建过程配置的参数

990bb1223e3f4bb084e8cb2bba5f47b0.png

图片
6.6 构建&运行&部署结果
  • 构建过程

213b71abe2944b79d313d6de2cc0cea2.png

图片
  • 部署结果

3511f4736b4b477e6d6891ab5a077658.png

图片

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 学习&参考文章
  • https://docs.docker.com/engine/reference/commandline/docker/

  • https://yeasy.gitbooks.io/docker_practice/

  • https://github.com/spotify/docker-maven-plugin

  • https://dmp.fabric8.io/

  • https://github.com/jilongliang/springboot

  • https://www.cnblogs.com/kakaln/p/7872873.html

  • https://www.cnblogs.com/lucoo/p/10209892.html


 
 
 
 
 
 
 
 
 
 
来源:jianshu.com/p/bdb0642b7495
版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
 
 
 
 
 
 
 
 
 
 
 
 

BAT等大厂Java面试经验总结

728706af1880b1d4c2f7b5484dcf5c2b.png

想获取 Java大厂面试题学习资料

扫下方二维码回复「BAT」就好了

回复 【加群】获取github掘金交流群
回复 【电子书】获取2020电子书教程
回复 【C】获取全套C语言学习知识手册
回复 【Java】获取java相关的视频教程和资料
回复 【爬虫】获取SpringCloud相关多的学习资料
回复 【Python】即可获得Python基础到进阶的学习教程
回复 【idea破解】即可获得intellij idea相关的破解教程
关注我gitHub掘金,每天发掘一篇好项目,学习技术不迷路!

00bb66cfeec1aeeff2b1bce4453b3434.png

回复 【idea激活】即可获得idea的激活方式

回复 【Java】获取java相关的视频教程和资料

回复 【SpringCloud】获取SpringCloud相关多的学习资料

回复 【python】获取全套0基础Python知识手册

回复 【2020】获取2020java相关面试题教程

回复 【加群】即可加入终端研发部相关的技术交流群

阅读更多

为什么HTTPS是安全的

因为BitMap,白白搭进去8台服务器...

《某厂内部SQL大全 》.PDF

字节跳动一面:i++ 是线程安全的吗?

大家好,欢迎加我微信,很高兴认识你!

在华为鸿蒙 OS 上尝鲜,我的第一个“hello world”,起飞!

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!

07856baca914467ff2b0379868025370.png

5007340218ac24fe2e4568ebc358eed3.gif

就给个“在看96b07ff668b2ff2db8c17fd4faf68b72.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值