一、基本框架
二、项目说明
三、本地部署
打包时通常使用
mvn clean package,但是这种方式打包时不会将依赖进行打包,因此出来的jar包不可以单独使用,为了能够获取单独使用的jar包,需要在父工程中添加spring boot的打包插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.5</version>
</plugin>
</plugins>
</build>
- 对
springcloud-eureka-7001进行打包
mvn package spring-boot:repackage
-
查看
jar包 -
运行
jir包
java -jar XXX.jar
- 查看效果
四、环境准备
4.1 Docker入门
(1)Docker简介
- Docker是一个开源的应用容器引擎,基于Go语言,并遵循从Apache2.0协议开源。
- Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。 (Docker之前的虚拟化技术是虚拟机)
- 容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。
(2)Docker与传统虚拟机的对比
- 虚拟机:底层是硬件设备,操作系统,之上是虚拟机软件,然后安装子系统,之后才可以安装软件。[至少要安装两层系统,一个在硬件上,一个在虚拟机上]
- Docker:容器软件上面可以直接安装软件,只需要一层OS,更加透明,共享内核,减少开销
| 虚拟机 | 容器 | |
|---|---|---|
| 占用磁盘空间 | 非常大,GB级 | 小,MB甚至KB |
| 启动速度 | 慢,分钟级 | 快,秒级 |
| 运行形态 | 运行于Hypervisor上 | 直接运行在宿主机内核上 |
| 并发性 | 一台宿主机上十几个,最多几十个 | 上百个,甚至数百上千 |
| 性能 | 逊于宿主机 | 接近宿主机本地进程 |
| 资源利用率 | 低 | 高 |
简单一句话总结:Docker技术就是让我们更加高效地将任何应用,在Linux服务器部署和使用
(3)Docker安装
1)安装必要的软件包
sudo yum install -y yun-util\
device-mapper-persistent-data\
lvm2
yum-utils是管理repository及扩展包的工具,包含一系列yum工具,提供了yum-config-managerdevice mapper存储驱动程序需要device-mapper-persistent-data和lvm2
2)设置下载Docker镜像的仓库地址
sudo yun-config-manager\
--add-repo\
https://download.docker.com/linux/centos/docker-ce.repo
yun-config-manager管理主要的yum配置选项,切换启用或禁用的存储库,以及添加新的存储库--add-repo参数从指定文件或URL添加(和启用)软件仓库
3)列出安装的版本列表
yum list docker-ce --showduplicates |sort -r
4)安装指定版本
sudo yum install docker-ce-20.10.7.ce
5)查看版本号
docker -v
6)启动docker
sudo systemctl start docker// 启动sudo systemctl enable docker// 设置开机自启
7)添加阿里云镜像
vi /etc/docker/daemon.json
内容如下:
{
"registry-mirrors": ["https://6x0hh8io.mirror.aliyuncs.com"]
}
其中值需要在阿里云搜索容器镜像服务,点击镜像加速器,会看到自动生成的加速器地址:
(4)Docker基本命令快速入门
1)镜像相关的命令
镜像相当于是应用的安装包,在Docker部署的任何应用都需要先构建成镜像 镜像有两种基本的来源:
- 仓库下载(Docker官方,自己部署的私有仓库)
- 自己制作镜像
| 命令 | 说明 |
|---|---|
docker search 镜像名称 | 搜索镜像 |
docker pull 镜像名称 | 拉取镜像 |
docker images | 查看本地所有镜像 |
docker rmi -f 镜像名称 | 删除镜像 |
docker search openjdk
docker pull openjdk:8-jdk-alpine
2)容器相关的命令
容器是由镜像创建而来,现有镜像后有容器,容器是Docker运行软件的载体,每个应用都分别运行在Docker的每个容器中。
| 命令 | 说明 |
|---|---|
docker run -i 镜像名称:标签 | 运行容器(默认是前台运行) |
| -i 前台运行 -di 后台运行 -p 公开端口:容器端口 暴露端口号 | |
docker start/stop/restart 容器名称/ID | 启动/停止/重启容器 |
docker rm -f 容器名称/ID | 删除容器 |
docker ps | 查看运行的容器 |
docker ps -a | 查询所有容器,包括停止的容器 |
docker exec -it 容器ID /bin/bash | 进入容器内部 |
- 测试运行
nginx镜像(前台) 使用docker pull下载nginx镜像
使用docker run -i nginx启动镜像
另开启一个终端通过docker ps命令查看容器运行状态
关闭运行nginx的终端,并通过docker ps -a可以查看关闭的容器
- 测试运行
nginx镜像并公开90端口(后台) 使用docker run -di -p 90:80 nginx
通过IP访问nginx的90端口
4.2 Dockerfile镜像脚本
(1)Dockerfile简介
Dockerfile其实就是我们用来构建Docker镜像的指令集合,他可以让用户个性化定制Docker镜像,因为工作环境中的需求各种各样,网络上的镜像很难满足实际需求。
- Dockerfile常见命令
| 命令 | 作用 |
|---|---|
FROM image_name:tag | 从基础镜像上构建 |
MAINTAINER user_name | 声明镜像的作者 |
ENV key value | 设置环境变量(可多条) |
RUN command | 编译镜像时运行的脚本(可多条) |
CMD | 设置容器的启动命令 |
ENTRYPOINT | 设置容器的入口程序 |
ADD source_dir/file dest_dir/file | 将宿主机文件复制到容器中,如果是压缩文件将会自动解压 |
COPY source_dir/file dest_dir/file | 和ADD类似,如果有压缩文件不能解压 |
WORKDIR path_dir | 设置工作目录 |
ARG | 设置编译镜像时加入的参数 |
VOLUMN | 设置容器的挂载卷 |
- 镜像构建示意图
可以看到,新的镜像是从基础镜像一层一层叠加的,每安装一个软件,就在现有镜像的基础上增加一层
(2)使用Dockerfile制作微服务镜像
我们利用Dockerfile制作一个Eureka注册中心镜像
-
上传
Eureka的微服务jar包到Linux的/home目录下 -
编写
Dockerfile
因为要运行一个jar包,依靠
JDK来运行,因此基础镜像为JDK镜像
从外部传入参数,用于拷贝jar包,将外部jar包拷到镜像内部并命名为app.jar
暴露7001端口
最后设置启动命令
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
ADD ${JAR_FILE} /app.jar
EXPOSE 7001
ENTRYPOINT ["java", "-jar", "/app.jar"]
- 构建镜像
docker build --build-arg JAR_FILE=springcloud-eureka-7001-1.0-SNAPSHOT.jar -t eureka:v1 .
-
查看构建结果
-
运行
Eureka容器 -
验证构建结果
4.3 Harbor镜像仓库安装及使用
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,解决如何将本地Docker镜像传递到别的服务器上去。
除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry,相比之下Harbor具有很多优势:
- 提供分层传输机制,优化网络传输
Docker镜像是分层的,而如果每次传输都使用全量文件不经济,必须提供识别分层传输机制,以层的UUID为标识,确定传输对象
- 提供WEB界面,优化用户体验
- 只用镜像的名字进行传输很不方便,需要有一个用户界面以支持登录、搜索、区分公有私有镜像
- 支持水平扩展集群
- 当有用户对镜像的上传下载操作急用在某服务器,需要对相应的访问压力分解
- 良好的安全机制
- 企业中开发团队有不同的置位,能够分配不同的权限,具有更好的安全性
(1)Harbor安装--安装在Docker仓库服务器
- 安装前应先确定已安装了
Docker - 安装
docker-compose,Harbor安装时需要该软件
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/dockercompose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose\
sudo chmod +x /usr/local/bin/docker-compose\
如果github使用不稳定,则用一下网址进行下载:
curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
- 给
docker-compose添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
- 查看
docker-compose是否安装成功
docker-compose -version
- 下载Harbor压缩包(v2.3.2)
https://github.com/goharbor/harbor/releases
- 上传
Harbor压缩包并解压
tar -xzf harbor-offline-installer-v2.3.2.tgz
mkdir /opt/harbor
mv harbor/* /opt/harbor
cd /opt/harbor
- 修改
Harbor的配置
vi harbor.yml
hostname: 192.168.117.37
port: 85
- 安装
Harbor
./prepare
如果提示ERROR:the protocol is https but attribute ssl_cert is not set
运行完成后会自动下载一下配置文件:
./install.sh
- 启动
Harbor
docker-compose up -d 启动
docker-compose stop 停止
docker-compose restart 重新启动
- 访问
Harbor
默认账户密码:
admin/Harbor12345
(2)在Harbor创建用户和项目
- 创建项目
(3)本地镜像上传
- 给镜像打上标签
docker tag eureka:v1 192.168.117.87:85/springcloud/eureka7001:v1
- 推送镜像
docker push 192.168.117.87:85/springcloud/eureka7001:v1
- 把
Harbor地址加入到Docker信任列表中
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.117.87:85"]
}
可能出现的一些问题:
- 有可能会出现重启失败,是因为使用阿里云镜像配置的问题,只需要将
daemon.json修改为daemon.conf重启即可 - 如果报错为
Error response from daemon...,是因为Docker自从1.3.X之后docker registry交互默认使用的是HTTPS,但是搭建私有镜像默认使用的是HTTP服务,所以与私有镜像交时出现以上错误。解决方法为在docker server启动的时候,增加启动参数,默认使用HTTP访问。
vim /usr/lib/systemd/system/docker.service然后重启Docker:
systemctl restart docker
- 如果显示权限不够,应当使用
docker login登录后重新push
查看效果:
(4)测试服务器从Harbor中下载镜像
测试服务器也需要下载Docker,添加Harbor的新人列表,操作如上小结所述,此处不再赘述。
五、Jenkins + Docker + SpringCloud
5.1 整体流程
- 将SpringCloud项目代码上传到Gitlab服务器
- Jenkins从Gitlab拉取代码
- 提交到
SonarQube代码审查 - 使用Dockerfile编译生成镜像
- 上传到Harbor镜像仓库
- 测试机拉取镜像并发布应用 上述过程通过Jenkins流水线项目演示完成
5.2 上传代码
IDEA中点击VCS->Enable Version Control Integration->选择Git- 项目父工程右键点击
Git->add Git->Commit DirectoryGit->Repository->Remotes->粘贴GitLab中clone的地址Git->Repository->push
5.3 从Jenkins中拉取代码
-
创建一个名为
SpeingCloud的流水线项目 -
将脚本直接写在IDEA项目
SpringCloud中,因此Jenkins只需要拉取脚本即可。
-
在IDEA中创建
Jenkinsfile并生成拉取代码的脚本 -
生成的脚本中将一些参数写死,我们可以进行参数化构建,在Jenkins中勾选参数化构建:
-
重新编写脚本:
-
构建job:
-
查看构建结果
-
查看源码
5.4 编译打包
- 编译安装公共子工程
因为该工程不需要进行打包,因此应该将父工程中
pom文件的build插件分别添加到需要打包的微服务中服务器查看
- 编译构建微服务工程
构建结果
![]()
服务器查看
问题:在构建生产和消费模块的时候,由于依赖公共模块,构建失败
这个问题的原因是因为项目采用了父子工程,父工程中使用dependencyManagement进行依赖管理,然后在子工程中进行依赖的引入,然后子工程springcloud-consumer-dept-8080和springcloud-provider-dept-8001使用了子工程springcloud-api中的实例,在本地的依赖库中找不到实例的jar包,因此需要对父工程进行编译安装,这样在本地依赖库中就有整个项目的结构,就能够找到对应的jar包。
在jenkins服务器中查看本地依赖库:
修改后能够正常打包:
5.5 使用Dockerfile编译、生成镜像
利用
dockerfile-maven-plugin插件构建Docker镜像
- 在每个微服务项目的POM中加入
dockerfile-maven-plugin插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.5</version>
</plugin>
<!-- https://mvnrepository.com/artifact/com.spotify/dockerfile-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
-
添加
Dockerfile文件 -
添加构建脚本
-
查看jenkins服务器执行job前的docker镜像
-
执行job
下载docker相关依赖,并执行dockerfile:
查看Jenkins服务器生成的镜像:
5.6 上传镜像到Harbor服务器
-
Jenkins添加Harbor凭证
-
通过凭证ID生成脚本
-
修改脚本
// 脚本式语法结构
// Git凭证ID
def git_auth = "a73dc07c-4f1a-45cf-a8b3-f54c75629422"
// Git的URL地址
def git_url = "git@192.168.59.132:mygroup/springcloud.git"
// 镜像版本号
def tag = "latest"
// Harbor的url地址
def harbor_url = "192.167.117.87:85"
// Harbor的仓库名称
def harbor_preoject = "springcloud"
// Harbor登录凭证ID
def harbor_auth = "93d2878c-4678-4f9c-a52b-709b16cec99b"
node {
stage('拉取代码') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [],
userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('安装父工程'){
sh "mvn clean install"
}
stage('编译安装公共类和实体类'){
sh "mvn -f springcloud-api clean install"
}
stage('编译打包微服务工程') {
sh "mvn -f ${project_name} clean package spring-boot:repackage dockerfile:build"
}
stage('上传镜像') {
// 定义镜像名称
def imageName = "${project_name}:${tag}"
// 打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_preoject}/${imageName}"
// 凭证
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password',usernameVariable: 'username')]) {
// 登录
sh "docker login -u ${username} -p ${password} ${harbor_url}"
// 镜像上传
sh "docker push ${harbor_url}/${harbor_preoject}/${imageName}"
sh "echo '镜像上传成功'"
}
}
}
-
查看结果
-
查看Harbor服务器
5.7 测试服务器拉取镜像
安装
Publish Over SSH安装该插件可以实现远程发送Shell命令 通过ssh-copy-id IP将公钥发送至测试服务器
-
Jenkins配置插件
-
生成部署脚本
-
编辑脚本
-
Shell脚本
#! /bin/sh
# 接收外部参数
harbor_url=$1
harbor_preoject=$2
project_name=$3
tag=$4
prot=$5
imageName=$harbor_url/$harbor_preoject/$project_name:$tag
echo "$imageName"
# 查询容器是否存在,存在则删除
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
# 停掉容器
docker stop $containerId
# 删除容器
docker rm $containerId
echo "成功删除容器"
fi
# 查询镜像是否存在,存在则删除
imageId=`docker images | grep -w ${project_name} | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
# 删除镜像
docker rmi -f $imageId
echo "成功删除镜像"
fi
# 登录Harbor
docker login -u admin -p Harbor123456 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $prot:$prot $imageName
echo "容器启动成功"
- 启动job
启动前去看测试服务器中
docker images
Jenkins输出
测试服务器
访问