Jenkins+docker 部署SpringCloud微服务(单项目,多模块)

部署需要提前准备的环境:安装好Jenkins、docker、Maven、Jdk1.8、Git

说明:由于本例只说明如何部署,所以有关项目其他服务如nacos、mysql、redis、seata等默认已经安装好的;这里只演示如何部署SpringCloud/SpringBoot应用到docker;

一. Jenkins插件安全和全局环境配置

插件安装 进入Jenkins管理后台首页面板   系统管理→插件管理→可选插件

需要安装的插件: Pipeline Utility Steps(用于解析pom文件,因为后续创建的docker容器带了版本,解析pom去拿版本,如果你的DockerFile生成的容器不带版本,则不需要安装)

image

全局参数配置:进入Jenkins管理后台首页面板   系统管理→系统配置

在全局属性里面添加一个环境变量,不然使用mvn命令时可能会报以下错误:

........./jenkins5323864766359302328.sh: line 2: mvn: command not found
 查看系统PATH变量: echo $PATH
 将查询出的PATA添加到全局环境变量属性中

image

全局参数配置:进入Jenkins管理后台首页面板   系统管理→全局工具配置

编辑maven的setting.xml文件,设置远程仓库为阿里云,设置Docker打包插件白名单

<mirrors>
   <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
   </mirror>
</mirrors>

<pluginGroups>
   <pluginGroup>com.spotify</pluginGroup>
</pluginGroups>

配置maven的setting文件和本地仓库

image
设置git

image

配置Git账号密码:进入Jenkins管理后台首页面板   系统管理→Manage Credentials

点击添加凭据,范围为全局,输入用户名和密码点击确定,ID会自动生成;我的代码放在gitee,所以这里输入的是码云的账号密码

image

二. 开始新建构建项目

本演示项目来自一个开源的SpringCloudAlibaba项目 源码地址:https://gitee.com/liuyadu/open-cloud

components:  公用模块,包含启动的加载配置,工具类等公用的模块,其他服务可以引入,完成一些基本的配置;
platform:   基本的服务,包含base服务(用于获取基本数据),统一网关gateWay,统一用户认证中心 ,uaa-admin-server
services:   其他服务

这里我只构建 base-server、gateway、uaa-admin-server三个服务

image

Jenkins新建文件夹

点击新建任务,选择文件夹类型;之后在该文件夹下面创建所有的服务,统一管理。这边我已经创建好了,所以显示已存在

image

创建拉取代码任务项目

创建一个拉取代码的项目,在open-cloud文件夹里面,新建item,这里选择构建自由风格的软件项目,用于拉取我们的项目源码,这样就不需要每个服务都单独拉取一次了;

image

在源码管理里面选择Git,输入项目Git地址,然后选择我们之前就已经添加的gitee凭据,指定拉取的分支;

image

指定拉取的代码保存地址: 在Additional Behaviors里面新增行为,选择到指定本地分支;默认情况下拉取代码到Jenkins工作目录(默认是/var/lib/jenkins/workspace) 加上在jenkins创建的任务名称

image

因为我们有创建一个文件夹,在文件夹下面创建的任务,所以默认是 /var/lib/jenkins/workspace/open-cloud/pull-project,但是我不想显示pull-project,直接到open-cloud就行,所以我指定Git代码保存目录到open-cloud

image

点击保存,然后点击【立即构建】,拉取完之后就能在我们指定的路径下面找到源码了;

创建base-gateway服务

打包docker有两种思路:一种是maven先把打成jar包和Dockerfile,然后使用docker build成一个镜像,运行;另一种是使用maven的bulid工具,直接在本地打包输出到指定的docker host主机,需要开启2375端口给外界访问/配置ssh秘钥;

这边我是直接在服务器上使用maven的docker打包插件,打包到本地容器;源码pom坐标已经配置了maven docker打包插件,这边以部署gateway服务为例,其他服务器部署只需要修改一下名称即可;

image

在open-cloud文件夹下面,新建一个item,这里我叫base-gateway,选择流水线;如果不知道Pipeline流水线任务的的可以去看一下文档

    官方文档:https://www.jenkins.io/zh/doc/book/pipeline/
    w3cschool:https://www.w3cschool.cn/jenkins/jenkins-173a28n4.html

image

在流水线里面,编写自己的Pipeline脚本,Jenkins的Pipeline脚本支持直接编写Script和从SCM加载脚本文件。如果选择从SCM获取,则可以直接把脚本放到项目的源码里面,指定文件即可,为了方便我直接选择编写脚本。

image

脚本文件如下:

node {
   // 指定工作目录,必须指定,否则路径默认会是/var/lib/jenkins/workspace/open-cloud/base-gateway/
   dir('/var/lib/jenkins/workspace/open-cloud/') {
       def workspace = pwd()
       echo "workspace:${workspace}"
       def image_name = 'open.cloud/open-cloud-base-gateway'
       def container_name='open-cloud-base-gateway'
       def project_home = 'open-cloud/open-cloud-base-gateway'
       // docker 挂载目录,自行创建前面的目录路径
       def root_path = "/data/docker/work/${project_home}"

        //删除旧容器和镜像
       stage('RM 删除旧容器和镜像') {
          echo '================删除已经存在的容器和镜像=================='
          sh "/data/docker/work/docker-rm.sh ${container_name}"
       }
       //编译代码和依赖
       stage('Build 编译代码和依赖') {
          // Run the maven build
          echo "bulid components模块......."
          sh "mvn -f components/pom.xml -Dmaven.test.skip=true clean install package -P test"
          echo "bulid open-cloud-base-client......."
          sh "mvn -f platform/open-cloud-base-client/pom.xml -Dmaven.test.skip=true clean install package -P test"
          echo "bulid open-cloud-base-server......."
          sh "mvn -f platform/${container_name}/pom.xml -Dmaven.test.skip=true clean install package -P test dockerfile:build"
       }
       //读取pom文件获取 version 和 port
       def pom = readMavenPom file: 'pom.xml'
       def port = "${pom.properties.appPort}"
       //运行容器
       stage('Run 运行容器') {
         echo '================运行容器=================='
       sh "docker run -p ${port}:${port} -d --name ${container_name} --restart=on-failure -v ${root_path}:${root_path} -v ${root_path}/log:/logs ${image_name}:${pom.version}"
       }
    }
}

这里我把port统一在每个服务的pom中配置,bootstrap.yml启动配置读取pom中的即可,这样就可以保证我们在本地测试和docker部署的端口一致;

image
image

上面有一个sh文件用于判断docker中是否已经存在此容器和镜像,如果存在则删除; sh文件内容如下,需要注意的是如果sh文件你是在Windows上创建的,格式可能无法直接运行,需要编辑文件 set ff=unix

#!/usr/bin/env bash
IMAGE_NAME=$1
echo "$IMAGE_NAME"
if [ ! -n "$IMAGE_NAME" ]; then
  echo 参数不能为空
  exit 4
fi
echo '================获取镜像id=================='
IID=$(docker images | grep "$IMAGE_NAME" | awk '{print $3}')
echo 镜像id=$IID

if [ -n "$IID" ]; then
  echo 存在$IMAGE_NAME镜像
  docker rmi $IID
else
  echo 不存在$IMAGE_NAME镜像
fi

echo '================获取容器id=================='
CID=$(docker ps -aqf "name=$IMAGE_NAME")
echo 容器id=$CID
if [ -n "$CID" ]; then
  echo 存在$IMAGE_NAME容器,停止容器并删除
  docker rm -f $IMAGE_NAME
else
  echo 不存在$IMAGE_NAME容器
fi

最后保存,点击立即构建;等待构建完成....

image

注意:构建中如果出现 org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method java.util.Dictionary get java.lang.Object...错误,是因为读取pom文件时需要Jenkins安全签名认证,点击系统管理选择In-process Script Approval ,点击approval ,对拦截到的命令允许通过,重启Jenkins即可

image

  • 相同步骤,创建base-serve、uaa-admin-serve

image

docker ps -a 查看容器运行情况,三个服务正常运行。

image

如果需要指定服务的启动顺序,可以使用构建触发器,让项目在其他项目构建完成之后触发

image

原文地址:https://www.cnblogs.com/lwjQAQ/p/15006964.html