8.Jenkins+Docker+SpringCloud微服务持续集成
前言
通过前几章的学习,了解了持续集成概念以及相关技术的学习和使用
接下来学习构建一整套SpringCloud微服务+Docker+Jenkins的持续集成案例
环境
架构图

流程说明:
- 开发人员将代码提交到代码托管平台,如Gitlab、Github
- Jenkins 从代码托管平台拉取代码、编译、打包后,通过Docker容器技术构建成镜像
- jenkins将构建好的镜像上传到远程容器管理平台Harbor
- Jenkins通过连接项目部署服务器,拉取Harbor上的项目镜像,创建容器,启动服务
- 用户远程访问部署服务器上的服务
服务列表
| 服务器名称 | IP地址 | 安装的软件 |
|---|---|---|
| 代码托管服务器 | 192.168.2.217 | Gitlab |
| 持续集成服务器 | 192.168.2.244 | Jenkins、Maven、Docker |
| Docker仓库服务器 | 192.168.2.217 | Docker Harbor |
| 项目部署服务器 | 192.168.2.219/192 | Docker |
微服务项目
项目技术
SpringCloud + SpringBoot +Mysql
微服务项目结构

- cloud2022 父工程
- cloud-api-common 项目公共类、通用代码
- cloud-consume-order80 消费者,通过注册中心调用后端微服务 ,端口为80
- cloud-eureka-server7001 Eureka技术,微服务的注册中心1, 端口为7001
- cloud-eureka-server7002 Eureka技术,微服务的注册中心2,端口为7002
- cloud-provide-payment8001 服务提供者1,端口为8001
- cloud-provide-payment8002 服务提供者2,端口为8002
数据库结构

项目部分代码
@RestController
@Slf4j
public class OrderController {
public static final String PAYENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
// 注入自定义的负载均衡规则
@Resource
private MyLoadBlance myLoadBalancer;
@Resource
private DiscoveryClient discoveryClient;
@GetMapping (value = "/consume/payment/create")
public CommonResult<Payment> create(Payment payment) {
return restTemplate.postForObject(PAYENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping(value = "/consume/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") long id) {
return restTemplate.getForObject(PAYENT_URL+"/payment/get/"+id,CommonResult.class);
}
/**
* 测试自定义负载均衡算法,测试时,需要取消 restTemplate配置类的注解 @LoadBalanced
* @LoadBalanced 让RestTemplate具备默认轮询的负载策略,所以会跟自定义负载策略冲突
* @return
*/
@GetMapping(value = "/consume/payment/lb")
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if (instances == null || instances.isEmpty()) {
return null;
}
// 调用自定义的负载均衡策略
ServiceInstance serviceInstance = myLoadBalancer.instance(instances);
URI uri = serviceInstance.getUri();
System.out.println(uri.toString());
//http://192.168.109.1:8001/payment/lb
return restTemplate.getForObject(uri + "/payment/lb", String.class);
}
}
通过Http客户端工具RestTemplate工具访问Eureka注册中心的后端微服务(负载均衡)
实际测试接口
@GetMapping(value = "/consume/payment/get/{id}")
代码地址:
https://gitee.com/lucky_sungit/spring-cloud2022_jenkins
上述仓库是包含了后续的Jenkinsfile脚本以及shell脚本的完结版本的代码
本地部署
SpringCloud微服务部署
本地运行微服务
1)逐一启动微服务
2)使用 postman 测试功能是否可用
本地部署微服务
1)Springboot微服务项目打包
在每个微服务的pom.xml中导入打包插件
cloud-api-common无需配置该插件
<build>
<!-- 定义项目的上下文 -->
<finalName>cloud_80</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中 -->
</goals>
</execution>
</executions>
</plugin>
</build>
打包
如果在父pom下打包,会报错,所以需要整个install

然后clean 、package即可全部打包,或者单个微服务下打包
测试
先启动注册中心集群,然后启动服务提供者集群,最后启动消费者服务,通过http访问接口即可
Docker仓库
docker介绍以及用法暂不介绍
Harbor
简介

Harbor(港口,港湾)是一个用于存储和分发Docker镜像的企业级Registry服务器。
除了Harbor这个私有镜像仓库之外,还有Docker官方提供的Registry。相对Registry,Harbor具有很多优势:
1).提供分层传输机制,优化网络传输 Docker镜像是是分层的,而如果每次传输都使用全量文件(所以用FTP的方式并不适合),显然不经济。必须提供识别分层传输的机制,以层的UUID为标识,确定 传输的对象。
2).提供WEB界面,优化用户体验 只用镜像的名字来进行上传下载显然很不方便,需要有一个用户界面可以支持登陆、搜索功能,包括区分公有、私有镜像。
3).支持水平扩展集群 当有用户对镜像的上传下载操作集中在某服务器,需要对相应的访问压力作分解。
4).良好的安全机制 企业中的开发团队有很多不同的职位,对于不同的职位人员,分配不同的权限, 具有更好的安全性。
安装
Harbor需要安装在192.168.2.219上面
1)先安装Docker并启动Docker(已完成) 参考之前的安装过程
2)再安装Docker-compose
一键安装脚本
#! /bin/bash
echo "---------开始安装---------"
sleep 1
echo "############判断是否安装了docker##############"
if ! type docker >/dev/null 2>&1; then
cat >/etc/yum.repos.d/docker.repo<<EOF
[docker-ce-edge]
name=Docker CE Edge - \$basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/\$basearch/edge
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
echo 'docker 未安装';
echo '开始安装Docker....';
yum -y install docker-ce
echo '配置Docker开启启动';
systemctl enable docker
systemctl start docker
cat >> /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
systemctl restart docker
else
echo 'docker 已安装';
fi
echo "############判断是否安装了docker-compose##############"
if ! type docker-compose >/dev/null 2>&1; then
echo 'docker-compose 未安装';
echo '开始安装docker-compose....';
wget http://oss.moguit.cn/script//docker-compose-Linux-x86_64
mv docker-compose-Linux-x86_64 docker-compose
chmod +x docker-compose
mv docker-compose /usr/local/bin/
docker-compose -v
else
echo 'docker-compose 已安装';
fi
3)安装Harbor
下载安装包
https://github.com/goharbor/harbor/releases
上传服务器并解压
tar -xvf harbor-offline-installer-v1.9.2.tgz -C /opt
cd harbor
修改Harbor的配置
vi harbor.yml
hostname: 192.168.2.217
port:8888
安装Harbor
./prepare
/inistakk.sh
启动Harbor
docker-compose up -d 启动
docker-compose stop 停止
docker-compose restart 重启
访问Harbor
默认密码: admin Harbor12345 (可以在harbor.yml中修改)

操作
1) 创建项目
Harbor的项目分为公开和私有的:
公开项目:所有用户都可以访问,通常存放公共的镜像,默认有一个library公开项目。
私有项目:只有授权用户才可以访问,通常存放项目本身的镜像。
我们可以为微服务项目创建一个新的项目

2)创建用户


1) 给私有项目分配用户
进入cloud2022项目->成员


| 角色 | 权限说明 |
|---|---|
| 访客 | 对于指定项目拥有只读权限 |
| 开发人员 | 对于指定项目拥有读写权限 |
| 维护人员 | 对于指定项目拥有读写权限,创建 Webhooks |
| 项目管理员 | 除了读写权限,同时拥有用户管理/镜像扫描等管理权限 |
测试
把镜像上传到Harbor
1)配置harbor信任列表
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"],
"insecure-registries": ["192.168.2.217:8888"]
}
2)重启docker
systemctl restart docker
3)登陆harbor服务器
docker login -u admin -p harbor12345 http://192.168.2.217:8888
4)给镜像打上标签
docker tag eureka:v1 192.168.2.217:8888/cloud2022/eureka:v1
5) 推送镜像
docker push 192.168.2.217:8888/cloud2022/eureka:v1
6)拉取镜像
docker pull 192.168.2.217:8888/cloud2022/eureka:v1
7)创建实例
docker run -it -d --name=test =p 7001:7001 192.168.2.217:8888/cloud2022/eureka:v1
Jenkins持续集成
微服务项目上传到Gitlab

jenkins从Gitlab拉取源码

//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
node{
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
}
拉取jenkinsfile文件

提交到SonarQube代码审查
添加两个参数

每个项目的根目录下添加sonar-project.properties
sonar.projectKey=cloud-eureka-server7002
sonar.projectName=cloud-eureka-server7002
sonar.projectVersion=1.0
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.
sonar.java.source=1.8
sonar.java.target=1.8
#sonar.java.libraries=**/target/classes/**
sonar.sourceEncoding=UTF-8
注意:修改sonar.projectKey和sonar.projectName
修改Jenkinsfile构建脚本
//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
node{
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
stage('代码审查'){
def scannerHome = tool 'sonarqube-scanner' //全局工具
withSonarQubeEnv('sonar-env'){ //全局环境变量
sh """
cd ${current_project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
}
使用Dockerfile编译、生成镜像
利用dockerfile-maven-plugin插件构建Docker镜像
在每个微服务项目的pom.xml加入dockerfile-maven-plugin插件
<!--docker插件-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${project.artifactId}</repository>
<!-- <tag>${project.parent.version}</tag>-->
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>//该参数对应dockefile的 ARG
</buildArgs>
</configuration>
</plugin>
在每个微服务项目根目录下建立Dockerfile文件
#FROMjava:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 7002
ENTRYPOINT ["java","-jar","/app.jar"]
修改Jenkinsfile构建脚本
//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
//定义上传的镜像标签
def tag="latest"
node{
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
stage('代码审查'){
def scannerHome = tool 'sonarqube-scanner' //全局工具
withSonarQubeEnv('sonar-env'){ //全局环境变量
sh """
cd ${current_project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
stage("安装父工程"){//找不到父工程依赖,需要将父工程打入仓库
sh "mvn clean install"
}
stage("公共子服务安装"){
sh "mvn -f cloud-api-common clean install"
}
stage("构建镜像"){
//定义镜像标签
def imageName="${project_name}:${tag}"
sh "mvn -f ${project_name} clean package dockerfile:build"
}
}
注意:步骤{安装父工程} 如果出现找不到父工程依赖,需要手动把父工程的依赖上传到仓库中
上传到Harbor镜像仓库
//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
def git_url="http://192.168.2.217:8444/CICD/springcloud2022.git"
//Harbor的凭证
def harbor_url="192.168.2.217:8888"
//定义上传的镜像标签
def tag="latest"
//Harbor项目名称
def harbor_project_name="cloud2022"
//harbor的凭证
def harbor_auth="23d2b1c5-941f-4144-8aef-3228b11f24a7"
node{
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
stage('代码审查'){
def scannerHome = tool 'sonarqube-scanner' //全局工具
withSonarQubeEnv('sonar-env'){ //全局环境变量
sh """
cd ${current_project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
stage("安装父工程"){//找不到父工程依赖,需要将父工程打入仓库
sh "mvn clean install"
}
stage("公共子服务安装"){
sh "mvn -f cloud-api-common clean install"
}
stage("构建镜像"){
//定义镜像标签
def imageName="${project_name}:${tag}"
sh "mvn -f ${project_name} clean package dockerfile:build"
//给本地镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName} "
//登陆Harbor,并上传镜像到仓库
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登陆Harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//并上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
//删除本地镜像
sh "docker rmi ${imageName}"
sh "docker rmi ${harbor_url}/${harbor_project_name}/${imageName}"
}
}
使用凭证管理Harbor私服账户和密码
先在凭证建立Harbor的凭证,在生成凭证脚本代码

拉取镜像和发布应用
结构

注意:192.168.66.103服务已经安装Docker并启动安装 Publish Over SSH 插件
安装以下插件,可以实现远程发送Shell命令

配置远程部署服务器
拷贝公钥到远程服务器
ssh-copy-id 192.168.2.192
系统配置->添加远程服务器

如果path to key报错的话,填入jenkins所在主机的key
修改Jenkinsfile构建脚本

添加一个port参数

stage {构建镜像步骤} 添加模板代码
sshPublisher(publishers: [sshPublisherDesc(configName: "${host}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
编写deploy.sh部署脚本
#!/bin/sh
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
imagename=$harbor_url/$harbor_project_name/$project_name:$tag
##判断本地是都有容器
container_id=`docker ps -qa | grep $project_name | awk '{print$1}'`
if [ $container_id != "" ];then
echo "容器存在,即将删除"
docker rm -f $container_id
fi
##判断镜像是否存在
image_id=`docker images | grep $project_name | awk '{print$3}'`
if [ $image_id] != "" ];then
echo "删除镜像"
docker rmi $imagename
fi
##登陆Harbor
docker login -u admin -p Harbor12345 $harbor_url
##拉取镜像
docker pull $imagename
##启动实例
docker run -it -d --name=$project_name -p $port:$port $imagename
echo "容器启动成功"
上传deploy.sh文件到/opt/jenkins_shell目录下,且文件至少有执行权限!
chmod +x deploy.sh 添加执行权限
测试
部署方案优化
上面部署方案存在的问题:
1) 一次只能选择一个微服务部署
2) 只有一台生产者部署服务器
3) 每个微服务只有一个实例,容错率低
优化方案:
1) 在一个Jenkins工程中可以选择多个微服务同时发布
2) 在一个Jenkins工程中可以选择多台生产服务器同时部署
3) 每个微服务都是以集群高可用形式部署

设计Jenkins集群项目的构建参数
1) 安装Extended Choice Parameter插件支持多选框

2)添加参数
字符串参数:分支

多选框:项目名称

注意:不填的话,默认‘,’ 区分中文和英文


//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
def git_url="http://192.168.2.217:8444/CICD/springcloud2022.git"
//Harbor的凭证
def harbor_url="192.168.2.217:8888"
//定义上传的镜像标签
def tag="latest"
//Harbor项目名称
def harbor_project_name="cloud2022"
//harbor的凭证
def harbor_auth="23d2b1c5-941f-4144-8aef-3228b11f24a7"
node{
//项目名称数组
def selectedProjects="${project_name}".split(',')
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
stage('代码审查'){
for(int i = 0;i < selectedProjects.length;i++){
//取出每个项目的名称和端口
def project_info = selectedProjects[i]
//项目名称
def current_project_name = "${project_info}".split('@')[0]
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonar-env'){
sh """
cd ${current_project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
}
stage("安装父工程"){//找不到父工程依赖,需要将父工程打入仓库
sh "mvn clean install"
}
stage("公共子服务安装"){
sh "mvn -f cloud-api-common clean install"
}
stage("编译、构建本地镜像"){
for(int j = 0; j < selectedProjects.length; j++){
def current_project = selectedProjects[j]
def current_project_name = "${current_project}".split("@")[0]
def current_port = "${current_project}".split("@")[1]
//定义镜像标签
def imageName="${current_project_name}:${tag}"
sh "mvn -f ${current_project_name} clean package dockerfile:build"
//给本地镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName} "
//登陆Harbor,并上传镜像到仓库
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登陆Harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//并上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
//删除本地镜像
sh "docker rmi ${imageName}"
sh "docker rmi ${harbor_url}/${harbor_project_name}/${imageName}"
//远程调用
sshPublisher(publishers: [sshPublisherDesc(configName: 'master', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $current_project_name $tag $current_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo "${current_project_name}完成编译,构建镜像"
}
}
}
}
完成微服务多服务器远程发布
1) 配置远程部署服务器
拷贝公钥到远程服务器
ssh-copy-id 192.168.66.104
2)系统配置->添加远程服务器

3)修改Docker配置信任Harbor私服地址 重启Docker
4)添加参数
多选框:部署服务器



最终效果

5) 修改Jenkinsfile构建脚本
//gitlab的凭证
def jenkins_Id="b6ccfe64-2c07-4b33-a39c-beec91d4a026"
def git_url="http://192.168.2.217:8444/CICD/springcloud2022.git"
//Harbor的凭证
def harbor_url="192.168.2.217:8888"
//定义上传的镜像标签
def tag="latest"
//Harbor项目名称
def harbor_project_name="cloud2022"
//harbor的凭证
def harbor_auth="23d2b1c5-941f-4144-8aef-3228b11f24a7"
node{
//项目名称数组
def selectedProjects="${project_name}".split(',')
//定义主机
def servers="${server}".split(',')
stage('拉取代码'){
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${jenkins_Id}", url: "${git_url}"]]])
}
stage('代码审查'){
for(int i = 0;i < selectedProjects.length;i++){
//取出每个项目的名称和端口
def project_info = selectedProjects[i]
//项目名称
def current_project_name = "${project_info}".split('@')[0]
def scannerHome = tool 'sonarqube-scanner'
withSonarQubeEnv('sonar-env'){
sh """
cd ${current_project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
}
stage("安装父工程"){//找不到父工程依赖,需要将父工程打入仓库
sh "mvn clean install"
}
stage("公共子服务安装"){
sh "mvn -f cloud-api-common clean install"
}
stage("编译、构建本地镜像"){
for(int j = 0; j < selectedProjects.length; j++){
def current_project = selectedProjects[j]
def current_project_name = "${current_project}".split("@")[0]
def current_port = "${current_project}".split("@")[1]
//定义镜像标签
def imageName="${current_project_name}:${tag}"
sh "mvn -f ${current_project_name} clean package dockerfile:build"
//给本地镜像打标签
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName} "
//登陆Harbor,并上传镜像到仓库
withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {
//登陆Harbor
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//并上传镜像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}
//删除本地镜像
sh "docker rmi ${imageName}"
sh "docker rmi ${harbor_url}/${harbor_project_name}/${imageName}"
for(int i = 0; i < servers.length; i++){
def host = servers[i]
echo host
//远程调用
sshPublisher(publishers: [sshPublisherDesc(configName: "${host}", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $current_project_name $tag $current_port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
echo "${current_project_name}完成编译,构建镜像"
}
}
}
}
注意:多台部署服务器都需要创建目录以及脚本文件
/opt/jenkins_shell/deploy.sh
最终测试

8.Jenkins+Docker+SpringCloud微服务持续集成的更多相关文章
- Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上)
Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上) Jenkins+Docker+SpringCloud持续集成流程说明 大致流程说明: 1) 开发 ...
- Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成——部署方案优化
Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成--部署方案优化 之前我们做的方案部署都是只能选择一个微服务部署并只有一台生产服务器,每个微服务只有一个 ...
- 08 . Jenkins之SpringCloud微服务+Vue+Docker持续集成
简介 大致流程 /* 1.开发人员每天把代码提交到Gitlab代码仓库 2.jenkins从gitlab中拉取项目源码,编译并打包成war包,然后构建Docker镜像,将镜像上传到Harbor私有仓库 ...
- 使用Jenkins+Docker+Gitlab+Maven搭建持续集成环境
继使用Docker搭建Gitlab后 大致的步骤如下: 开发人员通过IDE工具(IntelliJ IDEA)将代码推送到gitlab. jenkins从gitlab中获取到源码,并使用maven编译. ...
- Gitlab+Jenkins+Docker实现net core持续集成
前言 在项目中使用这一套自动集成的体系之后,一直想找个时间总结出来,用于自己记录也打算将自己的所得分享给园友们,不经常写文章,可能会有错误的地方,希望各位不吝指正,我会及时的改正并表示感谢,希望大家能 ...
- asp.netcore+jenkins+docker+svn+centos7.2 持续集成,每天凌晨获取最新代码打包发布
运行环境: centos7.2服务器或则虚拟机 可以是腾讯云也可以是内网服务器,(如果是内网服务器需要用frp做内网穿透,这样才可以通过外网访问该服务器) svnserver 来托管代码 一.安装je ...
- SpringCloud微服务之跨服务调用后端接口
SpringCloud微服务系列博客: SpringCloud微服务之快速搭建EurekaServer:https://blog.csdn.net/egg1996911/article/details ...
- 云端基于Docker的微服务与持续交付实践
云端基于Docker的微服务与持续交付实践笔记,是基于易立老师在阿里巴巴首届在线技术峰会上<云端基于Docker的微服务与持续交付实践>总结而出的. 本次主要讲了什么? Docker Sw ...
- [置顶]
Docker学习总结(7)——云端基于Docker的微服务与持续交付实践
本文根据[2016 全球运维大会•深圳站]现场演讲嘉宾分享内容整理而成 讲师简介 易立 毕业于北京大学,获得学士学位和硕士学位:目前负责阿里云容器技术相关的产品的研发工作. 加入阿里之前,曾在IBM中 ...
- 十一、Docker搭建部署SpringCloud微服务项目Demo
环境介绍 技术选型:SpringCloud&SpringCloud Alibaba&Docker 微服务模块划分: 员工模块:ems-employees 部门模块:ems-depart ...
随机推荐
- 网卡DM9000裸机驱动详解
一.网卡 1. 概念 网卡是一块被设计用来允许计算机在计算机网络上进行通讯的计算机硬件.由于其拥有MAC地址,因此属于OSI模型的第2层.它使得用户可以通过电缆或无线相互连接. 每一个网卡都有一个被称 ...
- C#学习日记
2023年9月9日 工具visual stdio 2019 窗口名称修改 lable标签 button 点击事件 点击换颜色 formLearn.ActiveForm.BackColor = Colo ...
- Kubernetes-11:ConfigMap介绍及演示
ConfigMap存在的意义 ConfigMap 功能在 Kubernetes1.2版本引入,许多应用程序会从配置文件.命令行参数或环境变量中读取配置信息,ConfigMap API 给我们提供了向容 ...
- MarkDown语法教程(转)
https://blog.csdn.net/2301_77569009/article/details/137957203
- Serilog文档翻译系列(二) - 设置AspNetCore应用程序
Serilog 日志记录适用于 ASP.NET Core.此包将 ASP.NET Core 的日志消息通过 Serilog 进行路由,使你可以将有关 ASP.NET 内部操作的信息写入与应用程序事件相 ...
- Vue3 比 Vue2 快的体现-第一部分
Vue3 比 Vue2 快的原因 首先体现在 Diff算法的优化上, Vue2 中的 虚拟DOM对比采用全量对比策略,这样的话每次渲染也就把静态dom节点做对比了.在Vue3 中 Diff算法 优化了 ...
- 嵌入式Linux ubi文件系统制作、分区设置、只读文件系统,uboot启动参数root
当前平台, 基于君正的X10000平台的嵌入式Linux 系统 0 目的 我要设置根文件系统为可读写, 设置data分区上的文件系统为只读 1 设置各文件系统的读写属性 /bin/mount -o ...
- crypt.h:No such file or directory 报错处理
crypt.h:No such file or directory 报错处理 前言:本文初编辑于2024年9月28日 CSDN主页:https://blog.csdn.net/rvdgdsva 博客园 ...
- LeetCode 218. 天际线问题 (扫描线+优先队列)
扫描线+优先队列 https://leetcode-cn.com/problems/the-skyline-problem/solution/tian-ji-xian-wen-ti-by-leetco ...
- Android Qcom USB Driver学习(十四)
UDC-Gadget UDC:(USB Device Controller)用于管理和控制USB设备与主机之间的通信. Gadget:Android在此层实现了adb,mtp(Media Transf ...