标签搜索

目 录CONTENT

文章目录

基于Docker编译打包部署的Jenkins流水线方案

陈铭
2023-05-20 / 0 评论 / 0 点赞 / 127 阅读 / 2,134 字 / 正在检测是否收录...

Jenkins安装部署

Jenkins宿主机

防火墙关闭(避免麻烦)

# 关闭防火墙(很重要!!)
systemctl stop firewalld
systemctl disable firewalld

Jenkins安装

使用yum安装,jdk使用官方文档指定的openjdk11,经测试,使用orcale jdk8,无法启动jenkins

wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
yum upgrade
yum install java-11-openjdk
yum install jenkins
systemctl daemon-reload

Maven安装(可选)

这个可以不装,jenkins主要也是用容器来编译的

cd /opt
wget https://dlcdn.apache.org/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.tar.gz
# 解压
tar -zxvf apache-maven-3.9.2-bin.tar.gz

# 创建本地库
mkdir -p /opt/repo/maven

# 配置中央库
vim /opt/apache-maven-3.9.2/conf/settings.xml
# 配置本地库位置
<localRepository>/opt/repo/maven</localRepository>
# 配置国内源
<mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
       <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
</mirror>

# 配置环境变量
vim /etc/profile.d/maven.sh
# 内容如下
export MAVEN_HOME=/opt/apache-maven-3.9.2
export PATH=$PATH:$MAVEN_HOME/bin

# 刷新环境变量
source /etc/profile

Docker安装

# 安装docker社区版
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine && \
yum install -y yum-utils device-mapper-persistent-data lvm2 && \
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && \
yum makecache fast && \
yum install docker-ce
 
# 启动服务
systemctl enable docker
systemctl start docker

# 增加权限,jenkins的pipeline内执行docker命令时,默认使用jenkins用户执行shell(该用户没权限执行docker)
cd /var/run
chmod 777 docker.sock

模板镜像安装

我这边写了一个新项目,做了一下模板docker镜像,有了这些镜像,我们可以方便的实现😁:

  • 基于容器隔离的多环境编译
  • 基于容器隔离的服务部署
    image-1684588613296

deploy

build.sh
# 清除构建缓存
docker builder prune -a -f

image_name="jdk11"
version="latest"
if [ `docker ps -a --format "{{.Image}}" | grep ${image_name}:${version} | wc -l` -gt 1 ]; then
    echo "============================== 当前存在容器占用镜像 =============================="
    exit 1
fi

if [ `docker images --format "{{.Repository}}:{{.Tag}}" | grep ${image_name}:${version} | wc -l` -gt 0 ]; then
    docker rmi -f ${image_name}:${version}
fi
docker build -t $image_name .
Dockerfile
FROM centos:7

MAINTAINER Tony Chen <chenming7@ruijie.com.cn>

ENV JAVA_HOME="/opt/jdk_11"
ENV PATH="${JAVA_HOME}/bin:${PATH}"

# 添加tar
# 复制本地的jdk_11.tar.gz到容器内的/opt/jdk_11.tar.gz
COPY jdk_11.tar.gz /opt/jdk_11.tar.gz

RUN cd /opt && tar zxvf /opt/jdk_11.tar.gz
RUN mv /opt/jdk-11.0.19 /opt/jdk_11

compile

build.sh
# 清除构建缓存
docker builder prune -a -f

image_name="maven_jdk11"
version="latest"
if [ `docker ps -a --format "{{.Image}}" | grep ${image_name}:${version} | wc -l` -gt 1 ]; then
    echo "当前存在容器占用镜像,请先清除容器后再构建镜像"
    exit 1
fi

if [ `docker images --format "{{.Repository}}:{{.Tag}}" | grep ${image_name}:${version} | wc -l` -gt 0 ]; then
    echo "存在残留同名镜像,正在清除"
    docker rmi -f ${image_name}:${version}
fi
echo "开始构建镜像"
docker build --no-cache -t $image_name .
Dockerfile
FROM centos:7

MAINTAINER Tony Chen <chenming7@ruijie.com.cn>

ENV JAVA_HOME="/opt/jdk_11"
ENV PATH="${JAVA_HOME}/bin:${PATH}"

ENV MAVEN_HOME="/opt/maven_3.9.2"
ENV PATH="${MAVEN_HOME}/bin:${PATH}"

# 添加jdk和 maven
# 复制本地的jdk_11.tar.gz到容器内的/opt/jdk_11.tar.gz
COPY jdk_11.tar.gz /opt/jdk_11.tar.gz
COPY maven_3.9.2.tar.gz /opt/maven_3.9.2_11.tar.gz

RUN cd /opt && tar zxvf /opt/jdk_11.tar.gz
RUN mv /opt/jdk-11.0.19 /opt/jdk_11

RUN cd /opt && tar zxvf /opt/maven_3.9.2_11.tar.gz
RUN mv /opt/apache-maven-3.9.2 /opt/maven_3.9.2

安装步骤

如上图所示,找到你所需的镜像,安装镜像

bash build.sh

验证安装

访问 http://<jenkins_ip>:8080/

配置Jenkins的MAVEN_HOME(可选)

访问http://<jenkins_ip>:8080/manage/configure
image-1684588768179

部署目标机配置

Jenkins的作用在于编译打包,目标机则承接打包文件,启动对应服务
环境准备:

  • docker:安装方法同上,记得赋权docker.sock
  • 关闭防火墙

流水线总体设计

流程图

设计思路

编译环境隔离

我关注什么?

  • 编译应该够快,别让我下半天依赖
  • 编译无残留,我只要最后的jar
  • 让我方便选择编译环境,JDK8? JDK11?
    解决方案
  • 编译要快?那么jenkins宿主机统一放置依赖本地库,编译时进行挂载
  • 编译无残留?那我容器内编译完,干掉容器就得了
  • 多种编译环境?那我预先做几个编译镜像,让用户执行流水线时进行选择就行

运行环境隔离

我关注什么?

  • 不要裸机跑服务,中个木马,整台机器都得寄😭!
  • 资源可调控,我想让哪个服务分配多少cpu和内存都行
  • 部署要快,别让我等太久!
    解决方案
  • 不要裸机?那就容器内跑吧
  • 资源可调?docker的参数一键搞定
  • 部署要快?容器已经很快了,如果只传输编译后的打包jar,通过挂载jar形式运行容器,IO不会很久的

流水线

Jenkinsfile

pipeline {
    agent any
    environment {
        // 宿主机配置
        JENKINS_SSH_PASSWORD = "xxx"
        // git配置
        GIT_URL = "xx.xx.xx.xx"
        GIT_PORT = "xxxx"
        GIT_USERNAME = "xxxx@xxx.xx.xx"
        GIT_PASSWORD = "xxx"
        // 部署机配置
        DEPLOY_SSH_USERNAME = "xxx"
        DEPLOY_SSH_PASSWORD = "xxx"
        DEPLOY_SSH_PORT = "xx"
        DEPLOY_JAR_PATH = "/devops/jar"
        DEPLOY_JAR_NAME = "${MODUEL}-${VERSION}.jar"
        DEPLOY_JAR = "${MODUEL}/target/${DEPLOY_JAR_NAME}"
        // docker配置
        CONTAINER_NAME = "${PROJECT.toLowerCase().replace("/","-")}-${MODUEL.toLowerCase()}"
        
    }
    parameters { 
        choice(name: 'GIT', choices: ['gogs'], description: 'GIT仓库')
        string(name: 'PROJECT', defaultValue: 'chenming7/MyWeb', description: '项目名')
        string(name: 'MODUEL', defaultValue: 'Web', description: '模块名')
        string(name: 'VERSION', defaultValue: '1.0-SNAPSHOT', description: '版本号')
        string(name: 'PORT', defaultValue: '443', description: '暴露端口,只能写一个')
        choice(name: 'COMPILE_SDK', choices: ['maven_jdk11'], description: '编译SDK')
        choice(name: 'DEPLOY_SSH_HOST', choices: ['192.168.217.134'], description: '部署机IP')
        choice(name: 'RUN_SDK', choices: ['jdk11'], description: '运行SDK')
    }
    stages {
        stage('Maven Build') {
            steps {

                // 拉去源码
                sh 'bash /var/lib/jenkins/shell/git.sh ${GIT} ${PROJECT}'

                // 编译打包
                sh "docker run -v $WORKSPACE:/opt/git -v /opt/repo/maven:/opt/repo/maven -w /opt/git --rm ${COMPILE_SDK} mvn package -pl ${MODUEL} -am"
            }

            // 该阶段的后处理
            post {
                // 成功时调用
                success {
                    // archiveArtifacts可以让我们下载指定的文件
                    archiveArtifacts "${DEPLOY_JAR}"
                    echo "编译完毕"
                }
            }
        }
        stage('Deploy'){
            steps {
                sh 'bash /var/lib/jenkins/shell/deploy.sh ${DEPLOY_SSH_HOST} ${DEPLOY_JAR_PATH} ${DEPLOY_JAR} ${CONTAINER_NAME} ${DEPLOY_JAR_NAME} ${PORT} ${RUN_SDK}'
            }
            
        }
    }
}

流水线相关脚本

git.sh

#!/bin/bash

GIT=$1
PROJECT=$2

function pull() {
    git pull
}

function clone(){
    if [ `ls -l | wc -l` -gt 1 ]; then
      pull
    else
      case $GIT in
          "gogs")
              GIT_USERNAME="xxxx"
              GIT_PASSWORD="xxxx"
              GIT_URL="xx.xx.xx.xx"
              GIT_PORT="xxxx"
              git clone http://$GIT_USERNAME:$GIT_PASSWORD@$GIT_URL:$GIT_PORT/$PROJECT.git .
              ;;
          "github")
              echo "stop $2"
              ;;
          *)
              echo "example: git.sh gogs chenming7/MyWeb"
              ;;
      esac
    fi
}

clone

deploy.sh

#!/bin/bash

DEPLOY_SSH_HOST=$1
DEPLOY_JAR_PATH=$2
DEPLOY_JAR=$3
CONTAINER_NAME=$4
DEPLOY_JAR_NAME=$5
PORT=$6
RUN_SDK=$7


function deploy() {
  case $DEPLOY_SSH_HOST in
  "192.168.217.134")
    DEPLOY_SSH_USERNAME="xxx"
    DEPLOY_SSH_PASSWORD="xxxx"
    DEPLOY_SSH_PORT="xxx"
    sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST rm -rf $DEPLOY_JAR_PATH/*
    sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST mkdir -p $DEPLOY_JAR_PATH
    sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST chmod 777 -R $DEPLOY_JAR_PATH
    sshpass -p $DEPLOY_SSH_PASSWORD scp -P $DEPLOY_SSH_PORT $DEPLOY_JAR $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST:$DEPLOY_JAR_PATH


    if [ `sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker ps -a -f name=$CONTAINER_NAME | wc -l` -gt 1 ]; then
      sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker rm -f $CONTAINER_NAME
    fi

    sshpass -p $DEPLOY_SSH_PASSWORD ssh -p $DEPLOY_SSH_PORT -q -o StrictHostKeyChecking=no $DEPLOY_SSH_USERNAME@$DEPLOY_SSH_HOST docker run -v $DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME:$DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME -p $PORT:443 --name $CONTAINER_NAME -d $RUN_SDK java -jar $DEPLOY_JAR_PATH/$DEPLOY_JAR_NAME
    ;;
  *)
    echo "example: bash /var/lib/jenkins/shell/deploy.sh 192.168.217.134 /devops/jar Web/target/Web-1.0-SNAPSHOT.jar chenming7-myweb-web Web-1.0-SNAPSHOT.jar 443 jdk11"
    ;;
  esac
}

deploy
0

评论区