1

🏆(不要错过!)【CI/CD技术专题】「Jenkins实战系列」(3)Jenkinsfile+DockerFile实...

 3 years ago
source link: https://my.oschina.net/liboware/blog/5165765
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

🏆(不要错过!)【CI/CD技术专题】「Jenkins实战系列」(3)Jenkinsfile+DockerFile实现自动部署 - 异次元の技术领域 - OSCHINA - 中文开源技术交流社区

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

  • 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="[email protected]: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 str−a"{str} -a "str−a"{str}x" != "x" ]或者使用if [[ -n str]]来判断shell语法中,{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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK