Jenkins+Harbor+gogs+docker+portainer+springboot实现devOps(企业实战)

本篇主要讲述springboot以及vue前后端分离项目,使用Jenkins拉取gogs代码仓库源码,构建Docker镜像并推送至Harbor仓库,使用docker 可视化部署工具【portainer】部署生产服项目,编写shell脚本,至于jenkins、harbor、gogs、portainer 请自行安装部署,网上教程较多,比较简单
1、springboot 前后端分离项目,借用jenkins持续集成持续部署工具,使用shell脚本将项目编写好dockerFile 文件,生成镜像,并推送至镜像仓库
#!/bin/sh # 镜像仓库地址,我这里使用harbor镜像仓库,当然也可以使用阿里云镜像仓库
REGISTRY=hub.ywb.com
# 镜像仓库登录账号
REGISTRY_USER=admin
# 镜像仓库登录密码
REGISTRY_PASS=123456 # 镜像TAG
IMAGE_TAG=$REGISTRY/security
# 镜像名称
IMAGE_NAME=tv-api
# 镜像版本
IMAGE_VER=v2.2-$( date '+%Y%m%d' ).$BUILD_NUMBER # 构建项目名称
PROJECT_NAME=$JOB_NAME
# 构建项目的目录
PROJECT_DIR=$WORKSPACE
# 构建项目的编译目录
PROJECT_BUILD_DIR=$PROJECT_DIR/target
# 构建项目的服务访问端口
PROJECT_PORT=38101 # 当前日期
DATE=$( date '+%Y/%m/%d %H:%M:%S' )
# 返回值
RETVAL=0 echo "*******************************************************************************************" # 开始执行构建
echo "$DATE - 开始执行项目构建..." # 进入构建项目的编译目录
echo "$DATE - 进入项目构建目录 $PROJECT_BUILD_DIR"
cd $PROJECT_BUILD_DIR
# 获取编译后的 jar 包名称
JAR_NAME=$( ls | grep -i "jar" | grep -v grep | head -1 ) # 如果 JAR_NAME 为空
if [ -z "$JAR_NAME" ]; then
echo "$DATE - 未查询到项目 $PROJECT_NAME 编译的结果 $JAR_NAME"
exit $RETVAL
fi # 如果 JAR_NAME 不存在
if [ ! -f "$PROJECT_BUILD_DIR/$JAR_NAME" ]; then
echo "$DATE - 项目 $PROJECT_NAME 编译的文件 $JAR_NAME 不存在"
exit $RETVAL
fi echo "$DATE - 成功获取到项目 $PROJECT_NAME 的最终编译文件 $JAR_NAME" # 创建 Dockerfile
echo "$DATE - 创建 Dockerfile"
cat > Dockerfile <<EOF
FROM openjdk:8
MAINTAINER wanbin.yi@qq.com
# 在宿主机的 /var/lib/docker 目录下创建一个临时文件,并链接到容器的 /tmp,用于数据持久化,因为 springboot 内嵌 tomcat 默认使用 /tmp 作为工作目录
VOLUME /tmp
# 设置工作目录
WORKDIR /root
# 设置时区
RUN bash -c 'echo "Asia/Shanghai" > /etc/timezone'
# 添加 jar 包并检测
ADD $JAR_NAME /root/$JAR_NAME
RUN bash -c 'touch /root/$JAR_NAME'
# 设置 jvm 参数
ENV JAVA_OPTS="\
-server \
-Xms512m \
-Xmx2g \
-Xmn1g \
-XX:SurvivorRatio=8 \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m \
-XX:+UseParallelGC \
-XX:ParallelGCThreads=4 \
-XX:+UseParallelOldGC \
-XX:+UseAdaptiveSizePolicy \
-XX:+PrintGCDetails \
-XX:+PrintTenuringDistribution \
-XX:+PrintGCTimeStamps \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/ \
-Xloggc:/var/run/jvm-gc.log \
-XX:+UseGCLogFileRotation \
-XX:NumberOfGCLogFiles=5 \
-XX:GCLogFileSize=10M"
# 为了缩短 tomcat 启动时间,添加一个系统属性指向 “/dev/urandom” 作为 Entropy Source
ENTRYPOINT java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /root/$JAR_NAME
EXPOSE $PROJECT_PORT
EOF echo "$DATE - 创建 Dockerfile 完成" # 构建镜像
# 将镜像名转换为小写
IMAGE_NAME=$IMAGE_NAME | tr '[A-Z]' '[a-z]'
echo "$DATE - 开始构建镜像,镜像名称:$IMAGE_NAME:$IMAGE_VER" # 判断 docker 镜像中是否已存在,存在则删除之
IMAGE_ID=$( docker images | grep -i "$IMAGE_NAME" | grep -i "$IMAGE_VER" | grep -v grep | awk '{print $3}' | head -1 )
if [ ! -z "$IMAGE_ID" ]; then
echo "$DATE - 检测到镜像 $IMAGE_NAME:$IMAGE_VER 已存在,删除之..."
docker image rm -f $IMAGE_ID
fi docker build -t $IMAGE_NAME:$IMAGE_VER $PROJECT_BUILD_DIR
echo "$DATE - 构建镜像完成" # 推送镜像
echo "$DATE - 开始向镜像仓库推送"
docker tag $IMAGE_NAME:$IMAGE_VER $IMAGE_TAG/$IMAGE_NAME:$IMAGE_VER
docker login -u $REGISTRY_USER -p $REGISTRY_PASS $REGISTRY
docker push $IMAGE_TAG/$IMAGE_NAME:$IMAGE_VER
echo "$DATE - 向镜像仓库推送完成,请前往镜像仓库查看:http://$REGISTRY" echo "$DATE - 执行项目构建完成..." echo "*******************************************************************************************"
2、vue前端项目,同理使用jenkins生成镜像文件,并推送至镜像仓库
#!/bin/sh # 镜像仓库地址
REGISTRY=hub.ywb.com
# 镜像仓库登录账号
REGISTRY_USER=dev
# 镜像仓库登录密码
REGISTRY_PASS=123456 # 镜像TAG
IMAGE_TAG=$REGISTRY/demo
# 镜像名称
IMAGE_NAME=pms-web
# 镜像版本
IMAGE_VER=v2.2-$( date '+%Y%m%d' ).$BUILD_NUMBER # 构建项目名称
PROJECT_NAME=$JOB_NAME
# 构建项目的目录
PROJECT_DIR=$WORKSPACE
# 构建项目的最终编译目录
PROJECT_BUILD_DIR=dist
# 构建项目的正式脚本环境定义
PROJECT_PROFILE=prod # npm 指令
NPM=npm # 当前日期
DATE=$( date '+%Y/%m/%d %H:%M:%S' )
# 返回值
RETVAL=0 echo "*******************************************************************************************" # 开始执行构建
echo "$DATE - 开始执行项目构建..." # 进入构建项目的构建目录
cd $PROJECT_DIR
echo "$DATE - 进入项目构建目录 $PROJECT_DIR" # 检测是否有 npm 运行环境
echo "$DATE - 检测主机是否安装 $NPM 运行环境"
type $NPM > /dev/null
if [ $? -eq 0 ]; then
echo "$DATE - 当前主机存在 $NPM 运行环境,$NPM 版本:$( $NPM -v )"
else
echo "$DATE - 主机未安装 $NPM 编译环境,无法完成项目构建"
exit -1
fi # 执行 npm 初始化,根据项目的 package.json 安装依赖环境
echo "$DATE - 执行 $NPM 初始化,检测并安装项目依赖包,可能需要花费几分种时间,请耐心等待"
$NPM install
echo "$DATE - 完成 $NPM 初始化" # 执行 npm build,编译最终部署文件
echo "$DATE - 开始执行 $NPM 项目编译"
$NPM run build:$PROJECT_PROFILE
echo "$DATE - 完成 $NPM 项目编译,最终输出目录为:$PROJECT_DIR/$PROJECT_BUILD_DIR" # 检测项目编译后的目录是否存在
if [ ! -d $PROJECT_BUILD_DIR ]; then
echo "$DATE - 项目编译失败,未成功检测到最终编译目录:$PROJECT_DIR/$PROJECT_BUILD_DIR"
exit -1
fi echo "$DATE - 成功获取到项目 $PROJECT_NAME 的最终编译目录:$PROJECT_DIR/$PROJECT_BUILD_DIR" # 创建 nginx.conf
echo "$DATE - 创建 nginx 配置文件 nginx.conf,并计划用此文件替换 nginx 镜像中的 nginx.conf 文件"
cat > nginx.conf <<EOF
# 运行用户,可不设置
user nginx;
# 可开启进程数量,一般设置为和cpu核数一样
worker_processes 2;
# 日志路径和级别。这个设置可以放入全局块,http块,server块,级别依次为:debug|info|notice|warn|error|crit|alert|emerg
error_log /var/log/nginx/error.log;
pid /run/nginx.pid; # 最大文件打开数(连接),可设置为系统优化后的ulimit -HSn的结果
worker_rlimit_nofile 5120;
# cpu亲和力配置,让不同的进程使用不同的cpu
worker_cpu_affinity 01 10; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf; events {
# 网路连接序列化,防止惊群现象发生,默认为on
accept_mutex on;
# 一个进程是否同时接受多个网络连接,默认为off
multi_accept off;
# 事件驱动模型, select|poll|kqueue|epoll|resig|/dev/poll|eventport
# epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
use epoll;
# 单个后台worker process进程的最大并发链接数
worker_connections 1024;
} http {
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
'\$status \$body_bytes_sent "\$http_referer" '
'"\$http_user_agent" "\$http_x_forwarded_for"'; #access_log /var/log/nginx/access.log main;
access_log off; # 启用压缩
gzip on;
# 文件小于此大小不予压缩
gzip_min_length 1k;
gzip_buffers 4 16k;
# 压缩等级
gzip_comp_level 5;
# 压缩类型
gzip_types text/plain text/css text/javascript image/jpeg image/png image/bmp image/svg+xml font/ttf font/otf font/woff font/woff2 application/pdf application/xml application/json application/x-javascript application/x-httpd-php;
gzip_vary on;
gzip_static on; # 开启高效传输模式,默认为off,可以在http块,server块,location块
sendfile on;
# 每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限
sendfile_max_chunk 16k; # 读取客户端请求头缓冲大小
client_header_buffer_size 1k;
# 读取客户端请求体缓冲大小
client_body_buffer_size 16k;
# 客户端允许上传文件的最大值
client_max_body_size 256m; # 允许把httpresponse header和文件的开始放在一个文件里发布,作用是减少网络报文段的数量
tcp_nopush on;
# 内核会等待将更多的字节组成一个数据包,从而提高I/O性能
tcp_nodelay on; # 连接超时时间,默认为75s,可以在http,server,location块
keepalive_timeout 65; include /etc/nginx/mime.types;
default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf; server {
listen 80;
#listen [::]:80;
server_name localhost; charset utf-8; # Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf; location / {
root /usr/share/nginx/html/pc;
index index.htm index.html default.htm default.html;
autoindex on;
} error_page 404 /404.html;
location = /40x.html {
} error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
} }
EOF echo "$DATE - 创建 nginx.conf 完成" # 创建 Dockerfile
echo "$DATE - 创建 Dockerfile"
cat > Dockerfile <<EOF
FROM nginx
MAINTAINER wanbin.yw@qq.com
COPY nginx.conf /etc/nginx/nginx.conf
COPY $PROJECT_BUILD_DIR/ /usr/share/nginx/html/pc
EOF echo "$DATE - 创建 Dockerfile 完成" # 构建镜像
# 将镜像名转换为小写
IMAGE_NAME=$IMAGE_NAME | tr '[A-Z]' '[a-z]'
echo "$DATE - 开始构建镜像,镜像名称:$IMAGE_NAME:$IMAGE_VER" # 判断 docker 镜像中是否已存在,存在则删除之
IMAGE_ID=$( docker images | grep -i "$IMAGE_NAME" | grep -i "$IMAGE_VER" | grep -v grep | awk '{print $3}' | head -1 )
if [ ! -z "$IMAGE_ID" ]; then
echo "$DATE - 检测到镜像 $IMAGE_NAME:$IMAGE_VER 已存在,删除之..."
docker image rm -f $IMAGE_ID
fi docker build -t $IMAGE_NAME:$IMAGE_VER $PROJECT_DIR
echo "$DATE - 构建镜像完成" # 推送镜像
echo "$DATE - 开始向镜像仓库推送"
docker tag $IMAGE_NAME:$IMAGE_VER $IMAGE_TAG/$IMAGE_NAME:$IMAGE_VER
docker login -u $REGISTRY_USER -p $REGISTRY_PASS $REGISTRY
docker push $IMAGE_TAG/$IMAGE_NAME:$IMAGE_VER
echo "$DATE - 向镜像仓库推送完成,请前往镜像仓库查看:http://$REGISTRY" echo "$DATE - 执行项目构建完成..." echo "*******************************************************************************************"
3、jenkins构建历史记录

4、最终可以使用docker portainer可视化工具进行项目部署工作,从harbor镜像仓库拉取镜像开始部署




Jenkins+Harbor+gogs+docker+portainer+springboot实现devOps(企业实战)的更多相关文章
- 三万字无坑搭建基于Docker+K8S+GitLab/SVN+Jenkins+Harbor持续集成交付环境
写在前面 最近在 K8S 1.18.2 版本的集群上搭建DevOps环境,期间遇到了各种坑.目前,搭建环境的过程中出现的各种坑均已被填平,特此记录,并分享给大家! 文章和搭建环境所需要的yml文件已收 ...
- 构建gitlab+Jenkins+harbor+kubernetes的DevOps持续集成持续部署环境
构建gitlab+Jenkins+harbor+kubernetes的DevOps持续集成持续部署环境 整个环境的结构图. 一.准备工作 gitlab和harbor我是安装在kubernetes集群外 ...
- Jenkins+Harbor+Docker发布
使用Jenkins发布Docke 需要准备的,docker,jenkins,Harbor docker安装 安装依赖: # yum install -y yum-utils device-mapper ...
- docker 运行jenkins及vue项目与springboot项目(三.jenkins的使用及自动打包vue项目)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- docker 运行jenkins及vue项目与springboot项目(一.安装docker)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- docker 运行jenkins及vue项目与springboot项目(二.docker运行jenkins为自动打包运行做准备)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- docker 运行jenkins及vue项目与springboot项目(四.docker运行nginx)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- docker 运行jenkins及vue项目与springboot项目(五.jenkins打包springboot服务且在docker中运行)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- GitLab + Jenkins + Harbor 工具链快速落地指南
目录 一.今天想干啥? 二.今天干点啥? 三.今天怎么干? 3.1.常规打法 3.2.不走寻常路 四.开干吧! 4.1.工具链部署 4.2.网络配置 4.3.验证工具链部署结果 4.3.1.GitLa ...
- Jenkins中执行docker命令报错
Cannot connect to the Docker daemon. Is the docker daemon running on this host? 在配置Jenkins从Gitlab自 ...
随机推荐
- 记录--手把手带你开发一个uni-app日历插件(并发布)
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 相信我们在开发各类小程序或者H5,甚至APP时,会把uni-app作为一个技术选型,其优点在于一键打包多端运行,较为强大的跨平台的性能.但 ...
- 提升团队协作效率:欧奥PicHome打造无缝资料共享平台
1. 引言 在快节奏的工作环境中,团队成员需要快速访问和共享信息.有效的资料共享不仅提高工作效率,还能促进团队协作和创新.然而,许多团队仍在使用传统的文件共享方法,这些方法往往效率低下,难以满足现代工 ...
- Babel解决ES6不能被所有浏览器解析问题
一.简介 1.ES6的某些高级语法在浏览器环境甚至是Node.js环境中无法执行. 2.Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行执行. 二.安装Babel ...
- UE427-C++实现摄像机视角的移动,类似开镜效果
教程 方法 调整相机视野和弹簧臂的长度 //自带的tick函数内 需要使用DeltaTime if (bZoomIn) { ZoomFactor += DeltaTime / 0.5f; } else ...
- 一招搞定进制转换--java篇
java中进制转化只需要记住这两个方法,后续再遇到进制转换的问题,轻松破解! 进制转换的核心就是: 其他进制--->十进制--->其他进制 1.其他进制转成十进制 valueOf() 方法 ...
- Python爬虫爬取搜狐视频电影并存储到mysql数据库
数据获取方式:微信搜索关注[靠谱杨阅读人生]回复[电影].整理不易,资源付费,谢谢支持. 代码: 1 import time 2 import traceback 3 import requests ...
- 关于 ThreadLocalRandom 随机数生成器
ThreadLocalRandom 线程安全随机数获取. 示例随机整数:java.util.concurrent.ThreadLocalRandom.current().nextInt(); 线程Th ...
- yml和properties打印SQL日志信息
1.配置文件里面配置 第一种是properties类型如下 logging.level.com.datayes.mdi.dao.rdb.mommp.**=debug其中 com.datayes.mdi ...
- WPF实现树形下拉列表框(TreeComboBox)
前言 树形下拉菜单是许多WPF应用程序中常见的用户界面元素,它能够以分层的方式展示数据,提供更好的用户体验.本文将深入探讨如何基于WPF创建一个可定制的树形下拉菜单控件,涵盖从原理到实际实现的关键步骤 ...
- #莫比乌斯反演,杜教筛#洛谷 6055 [RC-02] GCD
题目 分析 如果令 \(u=pj,v=qj\) ,那么本质上就是让 \(gcd(i,u,v)==1\) 那就是 \(\sum_{i=1}^n\sum_{u=1}^n\sum_{v=1}^n[gcd(i ...