乐趣区

关于spring:SpringCloudDockerJenkinsGitLabMaven-实现自动化构建与部署实战

前言与初衷

本文章会波及 Docker 常见命令根底知识点联合不同场景实操一起应用。本文章会波及联合工作过程中部署不同环境服务器的我的项目案例场景为初心进行理论细讲。

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

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

什么是 DevOps?

DevOps(Development 和 Operations 的组合词)是一组过程、办法与零碎的统称,用于促成开发(应用程序 / 软件工程)、技术经营和品质保障(QA)部门之间的沟通、合作与整合,它是一种器重“软件开发人员(Dev)”和“IT 运维技术人员(Ops)”之间沟通单干的文化、静止或常规。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、公布软件可能更加地快捷、频繁和牢靠。更多对于 DevOps 的介绍可参阅:超赞!阿里云外部超全 K8s/ECS/RDS/OSS/DevOps/DTS 实战手册,提供下载!

它的呈现是因为软件行业日益清晰地意识到:为了按时交付软件产品和服务,开发和经营工作必须严密单干。

波及软件环境搭建内容

  • Centos7 装置 JDK1.8-u121
  • Centos7 装置 Maven3.6.1
  • Centos7 装置 Git
  • CentOS7 与 Git 配置免明码登陆
  • Docker 装置 GitLab
  • Docker 创立 NetWork 网络
  • Docker 装置 Registry 私服
  • Docker 装置 Jenkins

特地阐明

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

2、其中 JDK 和 Maven 是传统形式进行装置,因为自己 Centos 操作系统是有其他软件依赖它们,有时候传统形式装置软件会更好,这里不过多的论述。有些软件在 Docker 装置过程与应用过程并没传统形式的简略,比方:Jenkins。

须要筹备的工作有哪些

工程构造

关上 IDEA 或 Eclipse 新建一个 SpringBoot 的利用.

环境配置特地阐明

注意事项:其中 Gitlab、Registry、Jenkins 都装置在 node1 机器下面,也就是 node1 作为主机(master),node2 作为 slave(从机或副机),机器名起有意义或能辨别即可,举荐起 master 和 slave,这里就不作过多的论述,为了防止看文章有疑难,请看清单列表. 另外,关注民工哥技术之路公众号,回复“Java 全栈常识体系”,送你一份 40000 字超强总结,Java 开发全栈技术常识体系.PDF 手册!

SpringBoot 配置和代码详解
  • 工程的 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>
  • 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> 
  • env 环境变量文件

用于设置环境动静参数, 文件是以.env 为格局

JAVA_OPTS_DEFAULT=-Xmx512m
  • 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

参数阐明

WORKDIR 工作目录阐明进入容器此时会有一个.jar 是在 Dockerfile 的 ADD 增加进去

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

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

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

  • 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
  • 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

参数阐明

docker tag 和 docker push 命令是一起联合应用,先 tag 后 push,每个镜像名和版本是以冒号辨别,而 docker pull 依据状况应用。

# 将镜像打一下标签,而后安照标签进行推送到私服外面,标签名就以服务名即可
docker tag 镜像名: 版本号 私服门路 / 镜像名: 版本号

# 推镜像到私服外面
docker push 私服门路 / 镜像名: 版本号

查看镜像

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

  • 虚悬镜像

在 docker 编译不胜利会或者是新版本笼罩旧版本归类为虚悬镜像, 生成这个个镜像既没有仓库名,也没有标签,均为 <none>。一般来说,虚悬镜像曾经失去了存在的价值,是能够随便删除的。另外,关注民工哥技术之路公众号,回复“Java 全栈常识体系”,送你一份 40000 字超强总结,Java 开发全栈技术常识体系.PDF 手册!

  • 不同环境的配置文件

配置参数

不同环境配置参数内容

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();}
}

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

特地阐明

以开发环境为例子进行阐明:开发环境部署指标机器是与 Jenkins 机器同一台机器,个别状况,Jenkins 是独自一台机器,这里为了节俭本身电脑内存,故放在同一台机器进行演示与学习。

新建 maven 工程

点击 Jenkins 的新建工作菜单

参数化构建过程阐明
  • 增加参数

  • 参数阐明以开发环境为案例

  • 源码治理

  • Build 编译设置

示意疏忽测试单元类进行编译

clean install -U -Dmaven.test.skip=true
SSH Publishers 设置
  • 其中 SSH Server Name 就是在 http://jenkins 地址: 端口 /jenkins/configure 设置好进行抉择
  • Transfer Set Source file 传输文件的门路, 能够应用参数构建的占位符 ${serverPath}获取
  • Remote directory 近程文件目录,同理也参数构建的占位符 ${serverPath}获取

  • SSH Publishers shell 脚本 #!/bin/bash 示意通知终端应用 bash 解析器进行执行,而且只有第一行 bash 才无效。

    #!/bin/bash
    # 创立目录
    mkdir -p ${serverPath}
    # 切换目录
    cd ${serverPath}
    # 运行脚本
    sh build.sh  $server  ${appName}  ${version}  ${port} ${env} ${serverPath}
    构建与编译部署我的项目

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

构建 & 运行 && 部署后果
  • 构建过程

  • 部署后果

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

特地阐明

以测试环境为例子进行阐明:步骤流程简直一样,惟一是在 SSH Publishers 和源码寄存门路不一样,测试环境部署指标机器是与 Jenkins 机器不同一台机器。

新建 maven 工程

点击 Jenkins 的新建工作菜单

参数化构建过程阐明
  • 增加参数

  • 参数阐明以测试环境为案例

  • 源码治理

  • Build 编译设置

SSH Publishers 设置
  • 其中 SSH Server Name 就是在 http://jenkins 地址: 端口 /jenkins/configure 设置好进行抉择
  • Transfer Set Source file 传输文件的门路, 能够应用参数构建的占位符 ${serverPath}获取
  • Remote directory 近程文件目录,同理也参数构建的占位符 ${serverPath}获取
  • docker_server1 示意与 Jenkins 部署同一个宿主机,应用脚本有近程机器 shell 脚本操作免登陆操作。

  • 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 Shell 脚本

#!/bin/bash
# 切换文件目录
cd ${serverPath}
# 执行脚本
sh build.sh ${server}  ${appName}  ${version}  ${port}  ${env} ${serverPath}
构建与编译部署我的项目

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

构建 & 运行 & 部署后果
  • 构建过程

  • 部署后果

总结 & 倡议

1、此文章仅供提供参考学习指引,如须要零碎得学习能够依据本身找材料去学习。

2、以上问题都是依据集体理论学习过程中遇到的问题进行一个一个问题进行梳理与总结整顿,除了技术问题查很多网上材料通过进行学习之后整顿与分享。

3、在学习过程中也遇到很多艰难和疑点,如有问题或正点,望各位老司机多多指出或者提出倡议。自己会驳回各种好倡议和正确形式不断完善现况,人在成长过程中的须要优质的养料。

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

5、倡议看官网手册更权威,因为随着技术的倒退与迭代, 通常官网的文档更新较快,国内的网站材料更新较慢。

6、计算机是一门『做中学』的学科,不是会了再去做,而是做了才会。多练,常言道游刃有余。

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

8、心愿此文章能帮忙你更好理解什么(DevOps)是自动化构建镜像与部署,如何在 Docker+Jenkins+GitLab+Maven+SpringBoot&SpringCloud 主动构建镜像与部署服务利用,整个学习流程与搭建会有点小波折,并不会那么顺利,也心愿你看了此文章或者通过找材料进行亲身经历学习效果会更好。

作者:寅务 链接:jianshu.com/p/bdb0642b7495

退出移动版