前提概要
- Jenkins下用DockerFile自动部署Java项目,项目的部署放心推向容器化时代机制。
- 本节需要对jenkinsfile有点了解,对dockerfile有点了解,对shell有点了解,对docker有点了解
环境准备
新建-构建一个Maven项目
需要提一下,现在新安装的没有这个选项,需要在插件里安装一下 Maven Integration
java配置,其他配置查看以前文章
发布到服务器,DockerFile部署自动构建
Publish SSH配置
执行流程
- jenkins拉取代码仓库中的代码
- jenkins执行jenkinsfile文件(可指定文件名)
- 先在jenkins所在的服务器将拉取的项目build成docker镜像
- 将镜像发布到镜像仓库
- 在应用服务器的节点上将该镜像拉取下来(私有仓库需要用户名/密码)
- 在应用服务器上执行该镜像
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部署
代码语言:txt复制pipeline {代码语言:txt复制 agent {label 'master'}代码语言:txt复制 tools{代码语言:txt复制 maven 'maven'代码语言:txt复制 }代码语言:txt复制 environment {代码语言:txt复制 GIT_PROJECT_ADDR="git@gitee.com:uncleqiao/springboot-test.git" //项目的git地址代码语言:txt复制 JENKINS_WORKSPACE="/root/.jenkins/workspace" //jenkins存放文件的地址代码语言:txt复制 PROJECT_NAME="${JOB_NAME}" // 项目名代码语言:txt复制 JAR_NAME="sample-tezst-0.0.1-SNAPSHOT.jar" // 项目生成的jar的名字代码语言:txt复制 _NAME="sample-tezst" // 镜像名一般和项目名相同代码语言:txt复制 _ADDR="repository/qiao_namespace/${ _NAME}" // 镜像的位置代码语言:txt复制 VERSION_ID="${BUILD_ID}"代码语言:txt复制 }代码语言:txt复制 stages {代码语言:txt复制 stage('pullCode'){代码语言:txt复制 steps{代码语言:txt复制 echo 'This is a pullCode step'代码语言:txt复制 //git branch: "${BRANCH}", credentialsId: '1001', url: "${GIT_PROJECT_ADDR}"代码语言:txt复制 checkout scm代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 stage('Build') {代码语言:txt复制 steps{代码语言:txt复制 echo 'This is a Build step'代码语言:txt复制 // 在有Jenkinsfile同一个目录下(项目的根目录下)代码语言:txt复制 sh 'mvn clean package -Dmaven.test.skip=true'代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 // 创建目录(如果不存在),并把jar文件上传到该目录下代码语言:txt复制 stage('ssh') {代码语言:txt复制 steps{代码语言:txt复制 echo 'push jar to target server'代码语言:txt复制 sh '''代码语言:txt复制 ole_ _id=`docker s|grep ${ _NAME}|grep ${VERSION_ID}|awk '{print $3}'`代码语言:txt复制 if [[ -n "${ole_ _id}" ]]; then代码语言:txt复制 docker rmi -f ${ole_ _id}代码语言:txt复制 fi代码语言:txt复制 docker build -f Dockerfile --build-arg jar_name=${JAR_NAME} -t ${ _NAME}:${VERSION_ID} .代码语言:txt复制 new_ _id=`docker s|grep ${ _NAME}|grep ${VERSION_ID}|awk '{print $3}'`代码语言:txt复制 sudo docker tag ${new_ _id} ${ _ADDR}:${VERSION_ID}代码语言:txt复制 sudo docker push ${ _ADDR}:${VERSION_ID}代码语言:txt复制 '''代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 stage('run') {代码语言:txt复制 // 在应用服务器节点 test代码语言:txt复制 agent {代码语言:txt复制 node {代码语言:txt复制 label 'test'代码语言:txt复制 //customWorkspace "${SERVER_TARGET_PATH}" //此参数会初始化目录 注意填写代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 options {代码语言:txt复制 // 不让它切换到节点上自动从仓库拉取项目代码语言:txt复制 skipDefaultCheckout()代码语言:txt复制 }代码语言:txt复制 steps {代码语言:txt复制 echo 'pull and docker run'代码语言:txt复制 withEnv(['JENKINS_NODE_COOKIE=dontKillMe']) {代码语言:txt复制 sh '''代码语言:txt复制 sudo docker login --username=yourusername --password=yourpassword ccr.ccs.tencentyun.com代码语言:txt复制 sudo docker pull ${ _ADDR}:${VERSION_ID}代码语言:txt复制 container_id=`docker ps|grep ${ _ADDR}:${VERSION_ID}|awk '{print $1}'`代码语言:txt复制 if [ -n "${container_id}" ]; then代码语言:txt复制 docker rm -f "${container_id}"代码语言:txt复制 fi代码语言:txt复制 old_pid=`ps -ef|grep ${JAR_NAME}|grep -v grep|awk '{print $2}'`代码语言:txt复制 if [[ -n $old_pid ]]; then代码语言:txt复制 kill -9 $old_pid代码语言:txt复制 fi代码语言:txt复制 old_ =`docker s|grep ${ _ADDR}|grep ${VERSION_ID}`代码语言:txt复制 if [[ -n $old_ ]]; then代码语言:txt复制 old_ _id=`echo ${old_ }|awk '{print $3}'`代码语言:txt复制 docker rmi -f ${old_ _id}代码语言:txt复制 fi代码语言:txt复制 sudo docker run --name "${PROJECT_NAME}_${VERSION_ID}" -p 9001:8081 -d ${ _ADDR}:${VERSION_ID}代码语言:txt复制 '''代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制 }代码语言:txt复制}注意:
if -n str 这个命令在使用的时候如果str为空,也是true,可以使用 if [ -n {str}x" != "x"
]或者使用if [[ -n ![{str} ]]来判断
shell语法中,](https://math.jianshu.com/math?formula={str} ]]来判断 shell语法中,)()`
和 (两个单引号) 可以在子shell中执行命令,但是这儿$()不支持
idea没有jenkinsfile的语法提示,很容易出错,这个很难受
步骤一:拉取项目 在【pullCode】步骤中
checkout scm , 这个scm是创建jenkins流水线时选择的,属于特殊变量,代表了你的仓库信息,自动从仓库中获取项目
步骤二: 【Build】
将拉取下来的项目进行编译并打包
步骤三:【build_ 】
将打包好的项目build成docker镜像,然后推送到镜像仓库(这里可以分成两步)
获取已经存在的镜像
代码语言:txt复制ole_ _id=`docker s| grep ${ _NAME} | grep ${VERSION_ID}|awk '{print $3}'`删掉存在的镜像
代码语言:txt复制if [[ -n "${ole_ _id}" ]]; then代码语言:txt复制 docker rmi -f ${ole_ _id}代码语言:txt复制fi- 通过项目根目录下的Dockerfile来构建镜像
- -f: filename --build-arg <key=value> 给Dockerfile传递参数
- -t: 镜像的名称:版本 这里我将jenkins的构建次数当作镜像的版本
docker build -f Dockerfile --build-arg jar_name=${JAR_NAME} -t ${ _NAME}:${VERSION_ID} .获取构建好的镜像的id
代码语言:txt复制new_ _id=`docker s | grep ${ _NAME} | grep ${VERSION_ID} | awk '{print $3}'`根据生成的镜像,tag出一个名称空间不同的镜像
代码语言:txt复制sudo docker tag ${new_ _id} repoistory/qiao_namespace/${ _NAME}:${VERSION_ID}将镜像仓库能够识别的镜像推送到仓库
代码语言:txt复制sudo docker push repoistory/qiao_namespace/${ _NAME}:${VERSION_ID}步骤四:【run】
应用服务器拉取项目并且运行, 这一步要选择节点(应用服务器,如果是集群,就不用节点用scp登陆吧)
登陆到镜像仓库
代码语言:txt复制sudo docker login --username=yourusername --password=yourpassword repository从仓库中拉取刚才生成的镜像
代码语言:txt复制sudo docker pull repository/qiao_namespace/${ _NAME}:${VERSION_ID}查看已经存在的容器, 存在则删掉 存在则删掉 这里应该是一个数组,有点小问题,待修改
代码语言:txt复制container_id=`docker ps | grep ${ _ADDR}:${VERSION_ID} | awk '{print $1}'`代码语言:txt复制if [ -n "${container_id}" ]; then代码语言:txt复制 docker rm -f "${container_id}"代码语言:txt复制fi查看已经运行的同版本的项目, 存在则删掉
代码语言:txt复制pid=`ps -ef | grep ${JAR_NAME}| grep -v grep | awk '{print $2}'`代码语言:txt复制if [[ -n $pid ]]; then代码语言:txt复制 kill -9 $pid代码语言:txt复制fi查看已经存在的镜像
代码语言:txt复制old_ =`docker s|grep ${ _ADDR}|grep ${VERSION_ID}`代码语言:txt复制if [[ -n $old_ ]]; then代码语言:txt复制 old_ _id=`echo ${old_ }|awk '{print $3}'`代码语言:txt复制 docker rmi -f ${old_ _id}代码语言:txt复制fi运行容器
代码语言:txt复制sudo docker run --name "${PROJECT_NAME}_${VERSION_ID}" -p 9001:8081 -d ${ _ADDR}:${VERSION_ID}Dockerfile
文件内容如下
代码语言:txt复制FROM repository/qiao_namespace/myjdk8:v1默认jar包的名字 注意分隔符为 :- 这里是由jenkinsfile中build dockerfile时传递过来的
代码语言:txt复制ARG jar_name={jar_name:-sample-teszt-0.0.1-SNAPSHOT.jar}RUN 用于容器内部执行命令
代码语言:txt复制RUN mkdir -p /usr/local/project代码语言:txt复制WORKDIR /usr/local/project将项目放到/usr/local/project下
代码语言:txt复制COPY ./target/sample-teszt-0.0.1-SNAPSHOT.jar ./代码语言:txt复制EXPOSE 8081代码语言:txt复制CMD java -jar -Dserver.port=8081 springboot-test-0.0.1-SNAPSHOT.jar执行完毕后我们登陆到应用服务器,看到容器已经启动


