CI/CD技术专题「Jenkins实战系列」Jenkinsfile+DockerFile实现自动部署

Posted 洛神灬殇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CI/CD技术专题「Jenkins实战系列」Jenkinsfile+DockerFile实现自动部署相关的知识,希望对你有一定的参考价值。

每日一句

没有人会因学问而成为智者。学问或许能由勤奋得来,而机智与智慧却有懒于天赋。

前提概要

  • Jenkins下用DockerFile自动部署Java项目,项目的部署放心推向容器化时代机制。
  • 本节需要对jenkinsfile有点了解,对dockerfile有点了解,对shell有点了解,对docker有点了解

环境准备

新建-构建一个Maven项目

需要提一下,现在新安装的没有这个选项,需要在插件里安装一下 Maven Integration

java配置,其他配置查看以前文章

发布到服务器,DockerFile部署自动构建

Publish SSH配置

执行流程

  1. jenkins拉取代码仓库中的代码
  2. jenkins执行jenkinsfile文件(可指定文件名)
  3. 先在jenkins所在的服务器将拉取的项目build成docker镜像
  4. 将镜像发布到镜像仓库
  5. 在应用服务器的节点上将该镜像拉取下来(私有仓库需要用户名/密码)
  6. 在应用服务器上执行该镜像

jenkins配置

创建一个Pipeline SCM项目 jenkins项目名为sample-tezst (和发布的工程名保持一致)

  • Definition选择 【Pipeline Script from SCM】

  • Branch Specifier(blank for ‘any’):选择分支

  • Additional Behaviours: 添加邮箱通知的发送者

  • Script Path: 填写使用项目中的Jenkinsfile文件的名字

应用工程配置

在工程的根目录下创建Dockerfile文件和Jenkins_docker文件

jenkinsfile_docker文件内容如下:

docker集成docker部署
pipeline 
    agent label 'master'
    tools
        maven 'maven'
    
    environment 
        GIT_PROJECT_ADDR="git@gitee.com:uncleqiao/springboot-test.git" //项目的git地址
        JENKINS_WORKSPACE="/root/.jenkins/workspace"    //jenkins存放文件的地址
        PROJECT_NAME="$JOB_NAME"  			        // 项目名
        JAR_NAME="sample-tezst-0.0.1-SNAPSHOT.jar"   // 项目生成的jar的名字
        IMAGE_NAME="sample-tezst"                    // 镜像名一般和项目名相同
        IMAGE_ADDR="repository/qiao_namespace/$IMAGE_NAME"    // 镜像的位置
        VERSION_ID="$BUILD_ID"
    
    stages 
        stage('pullCode')
            steps
                echo 'This is a pullCode step'
                //git branch: "$BRANCH", credentialsId: '1001', url: "$GIT_PROJECT_ADDR"
                checkout scm
            
        
        stage('Build') 
            steps
                echo 'This is a Build step'
                // 在有Jenkinsfile同一个目录下(项目的根目录下)
                sh 'mvn clean package -Dmaven.test.skip=true'
            
        
        // 创建目录(如果不存在),并把jar文件上传到该目录下
        stage('ssh') 
            steps
                echo 'push jar to target server'
                sh '''
                    ole_image_id=`docker images|grep $IMAGE_NAME|grep $VERSION_ID|awk 'print $3'`
                    if [[ -n "$ole_image_id" ]]; then
                        docker rmi -f $ole_image_id
                    fi
                    docker build -f  Dockerfile --build-arg jar_name=$JAR_NAME -t $IMAGE_NAME:$VERSION_ID .
                    new_image_id=`docker images|grep $IMAGE_NAME|grep $VERSION_ID|awk 'print $3'`
                    sudo docker tag $new_image_id $IMAGE_ADDR:$VERSION_ID
                    sudo docker push $IMAGE_ADDR:$VERSION_ID
                '''
            
        
        stage('run') 
            // 在应用服务器节点 test
            agent 
                node 
                    label 'test'
                    //customWorkspace "$SERVER_TARGET_PATH"  //此参数会初始化目录 注意填写
                
            
            options 
                // 不让它切换到节点上自动从仓库拉取项目
                skipDefaultCheckout()
            
            steps 
                echo 'pull image and docker run'
                withEnv(['JENKINS_NODE_COOKIE=dontKillMe']) 
                    sh '''
                        sudo docker login --username=yourusername --password=yourpassword ccr.ccs.tencentyun.com
                        sudo docker pull $IMAGE_ADDR:$VERSION_ID

                        container_id=`docker ps|grep $IMAGE_ADDR:$VERSION_ID|awk 'print $1'`
                        if [ -n "$container_id" ]; then
                        	docker rm -f "$container_id"
                        fi
                        old_pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk 'print $2'`
                        if [[ -n $old_pid ]]; then
                            kill -9 $old_pid
                        fi
                        old_image=`docker images|grep $IMAGE_ADDR|grep $VERSION_ID`
                        if [[ -n $old_image ]]; then
                            old_image_id=`echo $old_image|awk 'print $3'`
                            docker rmi -f $old_image_id
                        fi
                        sudo docker run --name "$PROJECT_NAME_$VERSION_ID" -p 9001:8081 -d $IMAGE_ADDR:$VERSION_ID
                    '''
                
            
        
    

注意:

if [ -n str ] 这个命令在使用的时候如果str为空,也是true,可以使用 if [ -n s t r − a " str -a " stra"strx" != “x” ]或者使用if [[ -n s t r ] ] 来判断 s h e l l 语法中, str ]]来判断 shell语法中, str]]来判断shell语法中,()` 和 `` (两个单引号) 可以在子shell中执行命令,但是这儿$()不支持

idea没有jenkinsfile的语法提示,很容易出错,这个很难受

步骤一:拉取项目 在【pullCode】步骤中

checkout scm , 这个scm是创建jenkins流水线时选择的,属于特殊变量,代表了你的仓库信息,自动从仓库中获取项目

步骤二: 【Build】

将拉取下来的项目进行编译并打包

步骤三:【build_image】

将打包好的项目build成docker镜像,然后推送到镜像仓库(这里可以分成两步)

获取已经存在的镜像
ole_image_id=`docker images| grep $IMAGE_NAME | grep $VERSION_ID|awk 'print $3'`
删掉存在的镜像
if [[ -n "$ole_image_id" ]]; then
	docker rmi -f $ole_image_id
fi
  • 通过项目根目录下的Dockerfile来构建镜像
    • -f:[filename] --build-arg <key=value> 给Dockerfile传递参数
    • -t:镜像的名称:版本 这里我将jenkins的构建次数当作镜像的版本
docker build -f Dockerfile --build-arg jar_name=$JAR_NAME -t $IMAGE_NAME:$VERSION_ID .
获取构建好的镜像的id
new_image_id=`docker images | grep $IMAGE_NAME | grep $VERSION_ID | awk 'print $3'`
根据生成的镜像,tag出一个名称空间不同的镜像
sudo docker tag $new_image_id repoistory/qiao_namespace/$IMAGE_NAME:$VERSION_ID
将镜像仓库能够识别的镜像推送到仓库
sudo docker push repoistory/qiao_namespace/$IMAGE_NAME:$VERSION_ID

步骤四:【run】

应用服务器拉取项目并且运行, 这一步要选择节点(应用服务器,如果是集群,就不用节点用scp登陆吧)

登陆到镜像仓库
sudo docker login --username=yourusername --password=yourpassword repository
从仓库中拉取刚才生成的镜像
sudo docker pull repository/qiao_namespace/$IMAGE_NAME:$VERSION_ID
查看已经存在的容器, 存在则删掉 存在则删掉 这里应该是一个数组,有点小问题,待修改
container_id=`docker ps | grep $IMAGE_ADDR:$VERSION_ID | awk 'print $1'`
if [ -n "$container_id" ]; then
	docker rm -f "$container_id"
fi
查看已经运行的同版本的项目, 存在则删掉
pid=`ps -ef | grep $JAR_NAME| grep -v grep | awk 'print $2'`
if [[ -n $pid ]]; then
	kill -9 $pid
fi
查看已经存在的镜像
old_image=`docker images|grep $IMAGE_ADDR|grep $VERSION_ID`
if [[ -n $old_image ]]; then
	old_image_id=`echo $old_image|awk 'print $3'`
    docker rmi -f $old_image_id
fi

运行容器

sudo docker run --name "$PROJECT_NAME_$VERSION_ID" -p 9001:8081 -d $IMAGE_ADDR:$VERSION_ID

Dockerfile

文件内容如下

FROM repository/qiao_namespace/myjdk8:v1
默认jar包的名字 注意分隔符为 :- 这里是由jenkinsfile中build dockerfile时传递过来的
ARG jar_name=jar_name:-sample-teszt-0.0.1-SNAPSHOT.jar
RUN 用于容器内部执行命令
RUN mkdir -p /usr/local/project
WORKDIR /usr/local/project
将项目放到/usr/local/project下
COPY ./target/sample-teszt-0.0.1-SNAPSHOT.jar ./
EXPOSE 8081
CMD java -jar -Dserver.port=8081 springboot-test-0.0.1-SNAPSHOT.jar

执行完毕后我们登陆到应用服务器,看到容器已经启动

以上是关于CI/CD技术专题「Jenkins实战系列」Jenkinsfile+DockerFile实现自动部署的主要内容,如果未能解决你的问题,请参考以下文章

CI/CD技术专题「Jenkins实战系列」jenkins+pipeline构建自动化部署

CI/CD技术专题「Jenkins实战系列」重塑Jenkins服务进行自动合并的方案实现(纠正错误)

CI/CD技术专题「Jenkins实战系列」总结归纳Jenkins的安装使用和配置流程介绍

CI/CD技术专题「Jenkins实战系列」jenkins+pipeline构建自动化部署

CI/CD技术专题「Jenkins实战系列」Jenkinsfile+DockerFile实现自动部署

CI/CD技术专题「Jenkins实战系列」如何通过Gitlab对接Jenkins构建提交自动触发部署构建体系指南(上部)