docker+jenkins+gitlab 部署springcloud 项目

最近玩了下docker和jenkins而且实战了微服务的项目,在这里记录下实现细节。
这也是我第一次写博文,之前学习的东西都是记录在印象笔记上,这次打算分享出来,若是写的很差或有错误的地方,请见谅、请指正。废话很少说,如今开始 。 ==本教程适合新手新手新新手,大神请绕道==
这次用到的工具备docker、jenkins、gitlab, 项目是springboot2.0+ 的springcloud 项目 使用gradle构建,项目的构建过程不在赘述,不会的可自行百度,jenkins使用通用的war包方式运行,本地git和gitlab的搭建,便再也不这里写了,官网有很详细的教程地址:https://about.gitlab.com/installation/。后面我会在写一篇在docker中搭建gitlab和jenkins的文章 ,至于docker 的安装就一样不在赘述,网上教程一大堆。

1.安装jenkins

jenkins下载地址 而后下载稳定版本的war包
2655994-95dca10e0bbd4d7a.png
image.png
下载下来以后,放到本身喜欢的目录,在jenkins.war 包所在的目录下,运行 java -jar jenkins.war --httpPort=9090 命令,因为spring项目占用了8080端口,因此jenkins不在使用默认的8080,指定--httpPort=9090 端口 效果以下
2655994-136f57054c3fb16c.png
image.png
第一次运行jenkins时,控制台会打印一段比较重要的信息,新手常常容易忽略,以下图
2655994-6f712665e83e411c.png
image.png
其中1是jenkins生成的默认密码,第一次登录是须要用的, 2是密码存放位置 若是之后还使用默认密码,则能够再这个目录下找到,这段信息只有第一次运行时才打印。 好了,如今在浏览器输入 localhost:9090试试,你会看到以下界面,此界面也会告诉你密码存放路径,而且也是第一次运行才提示。输入密码,而后点击继续
2655994-cc57d73cf0c74a81.png
image.png
2655994-59529791bbc15170.png
image.png
点击安装推荐的插件,而后等待安装完成,进入管理界面,输入用户名,密码和邮件地址,邮件地址必输,不然没法保存。而后一路点击完成
2655994-d64258321aa52fce.png
image.png
最后开始愉快的玩耍吧。。
2655994-4974793e68ed1c4f.png
image.png
开始使用时,咱们须要配置你的jdk,gradle和Gitlab地址, 这里咱们只配置最基础和必须的项,先实现自动化部署在完善别的。点击系统管理 -> 全局工具配置
2655994-565f4badad4d0b3d.png
image.png
2655994-049a8d7cccb00697.png
image.png
1.点击新增jdk,这里有两种方式,一种是本机JAVA_HOME路径配置,注意,不带bin目录,一种是在线安装,在线安装有个要求是须要注册oracle帐户,嫌麻烦,用本地的。2.点击安装gradle ,一样自动安装或本机GRADLE_HOME 路径,这个没什么要求,只要你开心,选哪一个都行,我用本机的,上图
2655994-94ecd6514feb6c2a.png
image.png
点击保存,而后下载gitlab插件,点击系统管理 -> 插件管理->可选插件,搜索gitlab 选择gitlab插件,点击直接安装。等待安装完成
2655994-4817094e4cb728fe.png
image.png
回到系统管理->系统设置 找到gitlab 配置项,这里有三个选项,1.链接名称,可随便输,2.gitlab地址,如:http://git.xxxxxx.com,3.秘钥
2655994-a3a9e770ea81b00b.png
image.png
点击ADD添加TOKEN令牌, 选择gitlab api token,token的获取方式我在下面会上图
2655994-b7decc06964cde6a.png
image.png
获取gitlab private key 登陆gitlab, 点击右上角头像->settings -> account 复制private token ,此处token就是上面须要的api token
2655994-a0cdc35b93995bbe.png
image.png
输入api token,点击添加,在令牌那一项,选择你刚才输入的项,点击Test Connection ,显示 Success表示配置成功,最后点击保存。如图:
2655994-11239e2640871a93.png
image.png
到这里,基本配置就完成了,能够构建项目了。点击新建任务 -> 随便输入一个任务名称 -> 选择构建一个自由分隔的软件 -> 点击肯定
2655994-d09a31adc5947a92.png
image.png
这个界面上,gitlab Connection 即是你刚才配置的gitlab,描述中能够随便输写内容,不输也能够
2655994-f138543ee5f08e62.png
image.png
源码管理 -> 选择git 输入你要构建gitlab 项目的路径 -> 选择刚才配置的令牌 -> 输入要拉取得git分支 -> 点击保存
2655994-4c2e5d3134529605.png
到这里git的配置就完成了,咱们测试下项目是否拉取成功,回到主页,你会看到你所配置的工程 -> 点击工程名称
2655994-dc6ccccfd0523e65.png
image.png
点击当即构建,你会在左下方看到构建历史窗口
2655994-1ac447cce04a29a2.png
image.png
这里显示你的构建历史,#1表示第一次构建,后面会有#2. #3......
2655994-6406dfc0538e7fcd.png
image.png
点击 #1 进入构建界面 -> 点击 控制台输出, 你会看到刚才构建的日志信息
2655994-657f32d4d13911f9.png
image.png
最后显示Finished: SUCCESS 表示你构建成功
2655994-5780a50f61d4a878.png
image.png
此时,你的项目被clone到 jenkins目录下,就是开头说过的你存放密码的路径的上一级。或者本机当前用户下有个 .jenkins/workspace,在此目录下你还看到你拉取下来的项目
2655994-c8bf4576019f01cb.png
image.png

2.使用gradle将项目打包并使用docker启动

在这里我先说明下我项目工程的目录结构,在这里我只用三个服务,eureka-service、bussines-service、admin-service,整个项目的结构以下(注:本教程主要是讲解如何将项目自动化搭建到docker上,而不是部署spring-cloud微服务,因此像config-Service等待啥的都不要了,部署细节啥的也都不讲了,毕竟网上教程一大堆)
2655994-41eaf57e62b9e22a.png
image.png
分解过程步骤 ,首先,我先说明下个人实现一种简单的方式
1. 使用gradle将各个服务打成 jar 包
2. 将新打的jar包copy 到指定docker-compose所在目录( ==dockerfile 和 docker-compose 的编写我在后面会详细讲解== )
3. 中止并删除容器
4. 删除镜像
5. 启动docker-compose 从新构建镜像而且启动容器
先实现第一步,打jar 包, 这里 会用到shell 脚本, 不过放心,shell 脚本很是很是很是简单,并且我会给详细注释, 首先在咱们项目根目录下建个build.sh文件 内容以下
#!/bin/sh

echo "更新服务开始。。。。"

###jenkins 从 gitlab 上拉取的项目所在路径
home="/Users/Function/.jenkins/workspace/spring-cloud"

### 自定义的docker-compose.yml 文件所在路径
docker_home="/Users/Function/Documents/workspace/docker-workspace/spring-cloud"

### admin服务文件夹名
admin_home="/admin-service"
### eureka服务文件夹名
eureka_home="/eureka-service"
### business服务文件夹名
business_home="/business-service/business-service-impl"


### 判断admin服务路径是否存在

if [ ! -e ${home}${admin_home} ];then
echo "${admin_home} 不存在"
exit 1;
fi

### 判断eureka服务路径是否存在
if [ ! -e "${home}${eureka_home}" ];then
echo "${eureka_home} 不存在"
exit 1;
fi

### 判断bussines_home服务路径是否存在
if [ ! -e "${home}${business_home}" ];then
echo "${business_home} 不存在"
exit 1;
fi


### 执行项目根目录下gradlew文件

echo "清除上次构建文件......"
cd ${home}
sh ${home}/gradlew clean
sleep 3

echo "开始构建Admin服务...."
cd ${home}${admin_home}
sh ${home}/gradlew bootJar -x test
echo "Admin服务构建完成...."

sleep 3

echo "开始构建eureka服务...."
cd ${home}${eureka_home}
sh ${home}/gradlew bootJar -x test
echo "开始构建eureka服务构建完成...."

sleep 3

echo "开始构建business服务...."
cd ${home}${business_home}
sh ${home}/gradlew bootJar -x test
echo "Service服务构建完成...."

if [ ! $? -eq 0  ];then
echo "gradle 执行失败: $?"
exit 1;
fi


echo "将最新jar包移动到DOCKER目录. ${docker_home}"
if [ ! -e "${docker_home}" ]; then
echo "${docker_home} 不存在"
exit 1;
fi

echo "删除旧的jar..."
rm -rf ${docker_home}/*.jar


echo "开始移动Eurake.."
mv ${home}${eureka_home}/build/libs/eureka-service.jar ${docker_home}

echo "开始移动Admin.."
mv ${home}${admin_home}/build/libs/admin-service.jar ${docker_home}


echo "开始移动Business.."
mv ${home}${business_home}/build/libs/business-service-impl.jar ${docker_home}

### 进入 docker-compose 文件所在目录
cd ${docker_home}

echo "中止并删除启动的容器....."
### 先中止并删除 上一次根据docker-compose启动的容器 注:echo 中输入的是你本机电脑密码,用 shell 执行 docker 命令时须要sudo 权限
echo "ccz123456..." | sudo -S docker-compose down
sleep 1

echo "删除spring-cloud 服务镜像....."
### 删除上一次构建的spring-cloud项目镜像   其中 grep service 中的service 是镜像名中包含的字段,是生成镜像时能够指定,如镜像名为: sc-service ,编写docker-compose时会说明
echo "ccz123456..." | sudo -S docker rmi --force `docker images | grep service | awk '{print $3}'`
sleep 1

echo "构建spring-cloud新的服务镜像....."
### 构建镜像镜像
echo "ccz123456..." | sudo -S docker-compose build
sleep 1

echo "启动服务容器....."
### 构建镜像并启动容器
echo "ccz123456..." | sudo -S docker-compose up -d
shell就是这样了,是否是很是简单? 其中有不少地方大家能够自行优化。下面编写dockerfile 文件,dockerfile文件我也会写的很是简单,多余的东西就不往上加了,在 脚本中的docker_home目录下新建三个dockerfile文件,命名为dockerfile-admin、dockerfile-business、dockerfile-eureka (文件名随意,大家开心就行)其中dockerfile-admin内容以下
# 依赖的java版本
FROM java:8
# 在容器中建立工做目录
RUN mkdir /app
# 指定工做目录
WORKDIR /app
#将你本机docker-home 目录下的 admin-service.jar ADD 到 容器 工做目录下并命名为 app.jar (不重命名也行)
ADD admin-service.jar  /app/app.jar
# 执行环境 其中-Djava.security.egd=file:/dev/./urandom 是JVM 熵池 参数,想了解的可百度 
# --spring.profiles.active=docker 是springcloud 配置文件 application.yml文件配置项,当有多个application.yml时用来指定加载哪一个配置文件
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar","--spring.profiles.active=docker"]
# 开放8080端口
EXPOSE 8080
dockerfile-bussines、dockerfile-eureka 文件内容同样,只需将 ADD admin-service.jar /app/app.jar 中的 admin-service.jar 替换成 business-service.jar 和 eureka.jar 而且修改 EXPOSE business-service 端口 9090 和 eureka-service端口 8761. 接下来是docker-compose.yml,一样,在docker-home目录下新建文件 docker-compose.yml内容以下
version: "3" # docker-compose 版本
services:  # 服务
  eureka-service:  # 定义eureka-service 名字随意
      container_name: eureka-container  # 指定容器名 随意
      build:
         context: . # dockerfile 文件所在路径  点 指的是 dockerfile 文件在当前docker-compose.yml所在目录下
         dockerfile: dockerfile-eureka  # dockerfile 文件名
      image: eureka-service:v1  # 指定生成的镜像名 并打上tag 标签 v1
      hostname: eurekaservice   # 容器hostname
      ports:
        - "8761:8761"   # 暴露容器端口到主机


  business-service:
        container_name: business-container
        build:
          context: .
          dockerfile: dockerfile-business
        image: business-service:v1
        ports:
          -  "8020:8020"
        depends_on: # 当前容器依赖于eureka 容器 ,当前容器会在 eureka-service 容器启动后执行
          -  eureka-service
        links:  # 连接 注册到eureka   eurekaservice 我会在下面说明
          -  "eureka-service:eurekaservice"


  admin-service:
      container_name: admin-container
      build:
        context: .
        dockerfile: dockerfile-admin
      image: admin-service:v1
      ports:
        - "8080:8080"
      depends_on: # 当前容器依赖于以上两个容器
        - eureka-service
        - business-service

      links:
        - "eureka-service:eurekaservice"
        - "business-service"
这里须要说明下docker-compose.yml 文件中 links : - "eureka-service:eurekaservice" docker中,容器直接连接的方式有两种,一种是服务名方式,一种是别名的方式,而别名的方式必须是以 服务名:别名 来指定。否则,你会发现你的服务没法注册到eureka中 文件中的 eurekaservice 为spring-cloud项目配置文件application.yml 中eureka url 中的hostname ,缘由是docker 默认的网络模式为 bridge, 每一个容器的IP都不一样,使用localhost没法知足需求,因此用主机名来访问,三个服务的url都改用容器主机名的方式
2655994-37cdfc744da5e232.png
image.png
好了,到这里一切都已准备就绪,咱们实验下效果。提交修改过得项目到Gitlab ,打开jenkins -> 进入工程 -> 配置当前工程
2655994-993d66a1fc79e244.png
image.png
找到构建项 -> 增长构建步骤 -> 选择 执行shell
2655994-14c2379c496929e8.png
image.png
在命令中 输入你刚才建的 build.sh 脚本的路径 或者 直接将脚本内容考皮到命令框中,若是是路径,应该是 ~/.jenkins/workspace/spring-cloud/build.sh , 而后点击保存,点击当即构建
2655994-26555cbe5910b1e7.png
image.png
见证奇迹的时刻就要到了,当你点击当即构建以后,而后进入控制台,你会看到构建过程日志
由用户 xxx 启动
构建中 在工做空间 /Users/Function/.jenkins/workspace/spring-cloud 中
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url [http://git.xxxx.com/spring-cloud.git](http://git.xxxx.com/spring-cloud.git) # timeout=10
Fetching upstream changes from [http://git.xxxx.com/spring-cloud.git](http://git.xxxx.com/spring-cloud.git)
 > git --version # timeout=10
using GIT_SSH to set credentials 
 > git fetch --tags --progress [http://git.xxxx.com/spring-cloud.git](http://git.xxxx.com/spring-cloud.git) +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision c85486e6447c023c0e70f98885760761aaaa928e (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f c85486e6447c023c0e70f98885760761aaaa928e
Commit message: "修改shell了嘞嘞"
 > git rev-list --no-walk c85486e6447c023c0e70f98885760761aaaa928e # timeout=10
[spring-cloud] $ /bin/sh -xe /var/folders/26/b1nkkk7j22v7dx9mvdty84vr0000gn/T/jenkins3559310015219383127.sh
+ cd /Users/Function/.jenkins/workspace/spring-cloud/
+ chmod u+x build.sh
+ ./build.sh
更新服务开始。。。。
清除上次构建文件......
:admin-service:clean
:business-service:clean UP-TO-DATE
:eureka-service:clean
:business-service:business-service-api:clean
:business-service:business-service-impl:clean

BUILD SUCCESSFUL in 0s
5 actionable tasks: 4 executed, 1 up-to-date
开始构建Admin服务....
:business-service:business-service-api:compileJava
:business-service:business-service-api:processResources NO-SOURCE
:business-service:business-service-api:classes
:business-service:business-service-api:jar
:admin-service:compileJava
:admin-service:processResources
:admin-service:classes
:admin-service:bootJar

BUILD SUCCESSFUL in 4s
5 actionable tasks: 5 executed
Admin服务构建完成....
开始构建eureka服务....
:eureka-service:compileJava
:eureka-service:processResources
:eureka-service:classes
:eureka-service:bootJar

BUILD SUCCESSFUL in 2s
3 actionable tasks: 3 executed
开始构建eureka服务构建完成....

开始构建business服务....

:business-service:business-service-api:compileJava UP-TO-DATE
:business-service:business-service-api:processResources NO-SOURCE
:business-service:business-service-api:classes UP-TO-DATE
:business-service:business-service-api:jar UP-TO-DATE

:business-service:business-service-impl:compileJava
:business-service:business-service-impl:processResources
:business-service:business-service-impl:classes
:business-service:business-service-impl:bootJar

BUILD SUCCESSFUL in 2s
5 actionable tasks: 3 executed, 2 up-to-date
Service服务构建完成....

将最新jar包移动到DOCKER目录. /Users/Function/Documents/workspace/docker-workspace/spring-cloud
删除旧的jar...
开始移动Eurake..
开始移动Admin..
开始移动Business..
中止并删除启动的容器.....

Password:Removing admin-container   ... 
Removing busines-container ... 
Removing eureka-container  ... 
�[3A�[2K
Removing admin-container   ... �[32mdone�[0m
�[3B�[2A�[2K
Removing busines-container ... �[32mdone�[0m
�[2B�[1A�[2K
Removing eureka-container  ... �[32mdone�[0m
�[1BRemoving network spring-cloud_default

删除spring-cloud 服务镜像.....
Untagged: admin-service:v1
Deleted: sha256:8bb51f82162535270d6bc7274ea8cac1e0a98ca103facf6548056ca3a1bcb484
Deleted: sha256:60257e125ebc783f930f79f16516091204e99a4a9d0390dcefa63703cb8c598c
Deleted: sha256:0e7e5c3a29df6fb7142fa37da4fc00526341f5b966099e6125f728efd2c52a6e
Deleted: sha256:169fc43041641f26b1046cd843d1e347bfd557625b4b39e798b621042721437c
Untagged: busines-service:v1
Deleted: sha256:d8cd89f0b7eba9a0b31eda5ec36b83bb1da4ebabfc549a915af36a62a4173b32
Deleted: sha256:03fc157106a95d58a0233655e55c616a68ca76d1d72fbf58705072e6729a4caf
Deleted: sha256:67e010d66dbf3e30adbd94f5eb33ad893ce7bba97f0cccec676d5f0834c7f44f
Deleted: sha256:2e2005d82ca03e80ed71f3b5c3c9087d720d6e727e2286f01967ec6fb0318023
Untagged: eureka-service:v1
Deleted: sha256:bf7b59c1673b09613df678a0cfe0156e645dad6aa9230a0fe90af2fd89163acc
Deleted: sha256:df664e41f222cb957a484110824f4bb977011698247e13b1413ca4097d17f003
Deleted: sha256:93cb206e2f8772c8b7d1f84a7a46d67393cdd0d8c7e61d28461087c82c0fdeec
Deleted: sha256:60863060e250a714a33dea8bef0393a8ea5a4f75fa96c28cef084392059e1128


构建spring-cloud新的服务镜像.....
Building eureka-service

Step 1/6 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/6 : RUN mkdir /app
 ---> Using cache
 ---> 27c94e92d2a7
Step 3/6 : WORKDIR /app
 ---> Using cache
 ---> 49efed4c9ca0
Step 4/6 : ADD eureka-service.jar  /app/app.jar
 ---> 56270e100c2a
Step 5/6 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar","--spring.profiles.active=default"]
 ---> Running in 8a997301d5b3
Removing intermediate container 8a997301d5b3
 ---> 2134b5a800a4
Step 6/6 : EXPOSE 8761
 ---> Running in 26c507af1c50
Removing intermediate container 26c507af1c50
 ---> 593b51aa6fa4
Successfully built 593b51aa6fa4
Successfully tagged eureka-service:v1
Building busines-service

Step 1/6 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/6 : RUN mkdir /app
 ---> Using cache
 ---> 27c94e92d2a7
Step 3/6 : WORKDIR /app
 ---> Using cache
 ---> 49efed4c9ca0
Step 4/6 : ADD business-service-impl.jar  /app/app.jar
 ---> 638b8674ee26
Step 5/6 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar","--spring.profiles.active=docker"]
 ---> Running in 5774538bd4d9
Removing intermediate container 5774538bd4d9
 ---> 0505d456c863
Step 6/6 : EXPOSE 8020
 ---> Running in f9714296fe56
Removing intermediate container f9714296fe56
 ---> 8d2ab6dd3c19
Successfully built 8d2ab6dd3c19
Successfully tagged busines-service:v1
Building admin-service

Step 1/6 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/6 : RUN mkdir /app
 ---> Using cache
 ---> 27c94e92d2a7
Step 3/6 : WORKDIR /app
 ---> Using cache
 ---> 49efed4c9ca0
Step 4/6 : ADD admin-service.jar  /app/app.jar
 ---> 8eb5a94001ff
Step 5/6 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar","--spring.profiles.active=default"]
 ---> Running in f7e7ce480b15

Removing intermediate container f7e7ce480b15
 ---> cd478f10383b
Step 6/6 : EXPOSE 8080
 ---> Running in 8509924c9984
Removing intermediate container 8509924c9984
 ---> d31a4a4c3358
Successfully built d31a4a4c3358
Successfully tagged admin-service:v1
启动服务容器.....


Creating network "spring-cloud_default" with the default driver
Creating eureka-container ... 
�[1A�[2K
Creating eureka-container ... �[32mdone�[0m
�[1BCreating busines-container ... 

�[1A�[2K
Creating busines-container ... �[32mdone�[0m
�[1BCreating admin-container   ... 
�[1A�[2K
Creating admin-container   ... �[32mdone�[0m
�[1BFinished: SUCCESS
当最后 显示finished:SUCCESS 时,表示已经成功,因为在 build 中设置了 项目后台启动,因此这里只看到了构建过程,没有项目启动日志,若是须要,看官们可自行修改,只需将build.sh 最后 -d 去掉便可
2655994-3f5c04965e683103.png
image.png
最后,在终端输入docker-container ls 你会看到启动的三个容器
2655994-1ee4768f60f42d47.png
image.png
而后访问 0.0.0.0:8761,你会看到服务已经注册到eureka 上了
2655994-fa78b9ae20727107.png
image.png
OK 大功告成!后面你能够在优化一些关于jenkins自动构建的步骤,这种教程网上也不少,我就不列举了。有什么错误的地方请留言指正。项目代码和 docker文件我都放到了GitHub上,GitHup地址
2655994-fc5c4d4c1b4a7178.png
image.png