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镜像仓库拉取镜像开始部署

 

 

 

 

原文地址:https://www.cnblogs.com/ywbmaster/p/15529999.html