ps:

  此篇博客中还有许多地方是可以优化的,欢迎大家留言进行指教

1.拉取jenkins镜像

这里我基于jenkins官方镜像制作一个镜像,已经下载好git的,并上传到了私服harbor上

2.安装运行jenkins镜像

在运行镜像之前,我们先在本机上创建一个jenkins的挂载目录 /home/jenkins,并修改其权限

mkdir /home/jenkins
chown -R 1000:1000 /home/jenkins/

运行jenkins镜像

docker run -itd -p 9090:8080 -p 50000:50000  --privileged=true -v /home/jenkins:/var/jenkins_home -v /etc/localtime:/etc/localtime -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -v /opt/software/jdk1.8.0_231:/usr/local/jdk -v /opt/software/apache-maven-3.6.3:/usr/local/maven -v /script:/script  --name jenkins 192.168.197.181:7090/jenkins/jenkins:1.4.0
  • -itd 以交互的形式后台运行镜像
  • -p 9090:8080 将镜像的8080端口映射到服务器的9090端口
  • -p 50000:50000 将镜像的50000端口映射到服务器的50000端口
  • --name jenkins 给容器起一个别名
  • --privileged=true container内的root拥有真正的root权限
  • -v /home/jenkins:/var/jenkins_home, /var/jenkins_home目录为jenkins工作目录,我们将其挂在出来方便后续操作
  • -v /etc/localtime:/etc/localtime 让容器使用和服务器同样的时间设置。
  • -v $(which docker):/usr/bin/docker  docker相关
  • -v /var/run/docker.sock:/var/run/docker.sock docker相关
  • -v /opt/software/jdk1.8.0_231:/usr/local/jdk 挂载jdk
  • -v /opt/software/apache-maven-3.6.3:/usr/local/maven 挂载maven
  • -v /script:/script 挂载脚本文件

3.配置jenkins容器

容器启动成功后,输入http://ip:9090 即可看到jenkins的界面,首次运行时,要等待一会时间,之后就会变成下方的页面

docker镜像安装curl docker镜像安装tkinter_maven

 此时,需要输入一个初始管理员的密码,我们之前运行时,已经把jenkins的工作目录挂载到我们本地的/home/jenkins,输入以下指令得到密码。

cat /home/jenkins/secrets/initialAdminPassword

输入密码后,会出现安装插件的页面,我们这里选择安装推荐插件,等待安装结束

docker镜像安装curl docker镜像安装tkinter_git_02

安装完插件后,会进入设置管理员的帐号,这里我们设置一个管理员帐号

docker镜像安装curl docker镜像安装tkinter_docker镜像安装curl_03

 设置完管理员帐号后,会提示配置jenkins的URL,这个url就是可以访问jenkins页面的,我们这边不变更

docker镜像安装curl docker镜像安装tkinter_docker_04

若是之前下载插件失败,有可能是网络原因导致,所以在提示我们是否重新在下时,直接跳过,进入到设置管理员帐号。

配置完成之后,既可以进入jenkins页面,由于之前插件下载有问题,我们在系统设置中,修改jenkins下载地址为国内地址。

https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

docker镜像安装curl docker镜像安装tkinter_docker镜像安装curl_05

 

docker镜像安装curl docker镜像安装tkinter_docker_06

 4.添加gitee帐号,用于拉取代码使用

按照图示进行帐号添加,这个要记住我们设置的id,是用于拉取git代码的

docker镜像安装curl docker镜像安装tkinter_docker镜像安装curl_07

docker镜像安装curl docker镜像安装tkinter_git_08

docker镜像安装curl docker镜像安装tkinter_git_09

5.配置jdk,maven环境变量,和ssh远程

在构建任务之前,必须要配置jdk和maven的环境变量,否则jenkins就会走默认的环境变量,导致发生异常

在添加环境变量之前,path的一定要加上path+xx,否则不会生效

 

docker镜像安装curl docker镜像安装tkinter_docker_10

docker镜像安装curl docker镜像安装tkinter_git_11

配置ssh远程连接

这里现使用jenkins下载 Publish Over SSH 插件,接着在上图中拉到最下方,找到下图配置

docker镜像安装curl docker镜像安装tkinter_docker_12

6.创建一个job任务

docker镜像安装curl docker镜像安装tkinter_maven_13

docker镜像安装curl docker镜像安装tkinter_git_14

docker镜像安装curl docker镜像安装tkinter_docker_15

流水线脚本

#!groovy
pipeline{
	agent any
	
	environment {
		//项目模块名
		MODOULE="blue"
		//git仓库地址
		REPOSITORY="https://gitee.com/584634024/blue-space.git"
		//docker私有仓库项目地址
		DOCKER_RESPOSITORY_PATH="192.168.197.181:7090/blue"
		//打包分支
		BRANCH="master"
		//jenkins中填写的git凭证id
		USER="Liuwei"
		//项目pom文件地址(相对路径)
		POMPATH="pom.xml"
		//docker打包推送脚本路径
		SCRIPT_PATH="/script/build-image.sh"
		//镜像仓库下的镜像名称
		MTAG="blue/blue"
		//容器名称
		CONTAINER="blueContainer"
	}
	
	stages {
		stage('获取代码') {
			steps {
				echo "拉取gitee代码 gitee:${REPOSITORY}"
				deleteDir()
				git credentialsId:"${USER}", branch:"${BRANCH}", url:"${REPOSITORY}"
			}
		}
		stage('编译') {
			steps {
				echo "mvn打包"
				sh "java -version"
				sh "mvn -version"
				sh "mvn -f ${POMPATH} clean package -Dmaven.test.skip=true"
			}
		}
		stage('docker打包') {
			steps {
				echo "docker打包"
				sh "${SCRIPT_PATH} ${MODOULE} ${DOCKER_RESPOSITORY_PATH}"
			}
		}
		
		stage('远程部署') {
			steps {
				echo "docker打包"
				sshPublisher(publishers: [sshPublisherDesc(configName: 'blue', transfers: [
				    sshTransfer(cleanRemote: false, excludes: '', 
				    execCommand: '/bin/bash /script/docker.sh '+MTAG+' '+CONTAINER, 
				    execTimeout: 200000, 
				    flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', 
				    remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], 
				    usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
			}
		}
	}
}

docker打包推送脚本

#!/bin/bash

#需要打包的模块名
MODOULE=$1

#需要上传docker仓库地址
DOCKER_RESPOSITORY_PATH=$2

#远程仓库地址
HARBOR_PATH="http://192.168.197.181:7090"

#帐号
ACCOUNT="liuwei"

#密码
PASSWORD="Liuwei..123"


echo "==========构建docker镜像开始=============="

#获取时间
TIME=`date "+%Y%m%d%H%M"`

#获取当前项目git提交的版本号
GIT_REVISION=`git log -1 --pretty=format:"%h"`

#获取需要打包的镜像名
IMAGE_NAME=${DOCKER_RESPOSITORY_PATH}/${MODOULE}:${TIME}_${GIT_REVISION}

#如果是多模块任务需要去到指定的模块包下,执行该模块的Dockerfile
#cd ${MODOULE}

#构建docker镜像
docker build -t ${IMAGE_NAME} .
if [ $? -eq 0 ]; then
    echo "构建docker镜像成功"
else
    echo "构建docker镜像失败"
    exit 1
fi

#如果是多模块任务的话,需要切换回来
#cd -


echo "==========推送docker镜像开始=============="

#登录远程仓库
docker login ${HARBOR_PATH} -u ${ACCOUNT} -p ${PASSWORD}

if [ $? -eq 0 ]; then
    echo "登陆Harbor仓库成功"
else
    echo "登陆Harbor仓库失败"
    exit 1
fi

#推送镜像
docker push ${IMAGE_NAME}

if [ $? -eq 0 ]; then
	#删除镜像
	docker rmi ${IMAGE_NAME}
    echo "推送镜像成功"
else
	#删除镜像
	docker rmi ${IMAGE_NAME}
    echo "推送镜像失败"
	exit 1
    
fi

jenkins镜像脚本

==============================Dockerfile==============================
FROM jenkins/jenkins:lts

MAINTAINER liuwei

USER jenkins

#安装jenkins插件
COPY plugins.txt /usr/share/jenkins/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/plugins.txt



USER root
ARG dockerGid=996

#将jenkins用户放docker组,安装gosu
RUN echo "docker:x:${dockerGid}:jenkins" >> /etc/group \
    && apt-get update &&  apt-get install -y gosu \
    && apt-get install -y libltdl7 \
    && rm -rf /var/lib/apt/list/*


COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

===========================================plugins.txt================================
git:latest

=============================================entrypoint.sh============================
#! /bin/bash
set -e
chown -R 1000 "$JENKINS_HOME"
exec gosu jenkins /sbin/tini -- /usr/local/bin/jenkins.sh

远程服务器执行脚本

#!/bin/bash

#仓库名
MTAG=$1

#容器名称
CONTAINER_NAEM=$2

#镜像仓库ip地址或域名
IMAGE_NAME_URL="192.168.197.181:7090"

#远程仓库地址
HARBOR_PATH="http://192.168.197.181:7090"

#帐号
ACCOUNT="liuwei"

#密码
PASSWORD="Liuwei..123"

#映射端口号可以为空
PORT="7186"

#容器端口号可以为空
CONTAINER_PORT="7186"

#挂载目录可以为空
MOUNT_PATH="/out/logs"

#容器需挂载目录可以为空
CONTAINER_MOUNT_PATH="/out/logs"

#前一个容器tag部分
OLD=_old


#登录harbor远程仓库token
TOKEN=$(curl -iksL -X GET -u $ACCOUNT:$PASSWORD $HARBOR_PATH/service/token?account=${ACCOUNT}\&service=harbor-registry\&scope=repository:${MTAG}:pull|grep "token" |awk -F '"' '{print $4}')

if [ $? -eq 0 ]; then
    echo "登陆Harbor仓库成功"
else
    echo "登陆Harbor仓库失败"
    exit 1
fi

#获取最新标签
TAG=$(curl -ksL -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" ${HARBOR_PATH}/v2/${MTAG}/tags/list|awk -F '[' '{print $2}'|awk -F ']' '{print $1}'|sed 's/"//g'|sed 's/,/\n/g'| awk 'END {print}')

echo "harbbor_path=${HARBOR_PATH}"
echo "MTAG=${MTAG}"
echo "TAG=${TAG}"
#拉取镜像
echo "=====================拉取镜像============================="

IMAGE_NAME=${IMAGE_NAME_URL}/${MTAG}:${TAG}

docker pull ${IMAGE_NAME}

if [ $? -eq 0 ]; then
    echo "拉取镜像${IMAGE_NAME}成功"
	docker logout ${HARBOR_PATH}
else
    echo "拉取镜像${IMAGE_NAME}失败"
	docker logout ${HARBOR_PATH}
    exit 1
fi


#获取正在运行的模块容器id
CONTAINER_ID=`docker ps | grep -w ${CONTAINER_NAEM} | awk '{print $1}'`

#获取上一个镜像的标签(包含_old)
OLD_IMAGES_TAG=`docker images | grep ${OLD} | awk '{print $2}'`


#停掉正在运行的容器,并且容器的镜像标签进行变更
if [ "${CONTAINER_ID}" !=  "" ] ; then
    
	#获取当前运行容器镜像
	IMAGE=`docker ps | grep -w ${CONTAINER_NAEM} | awk '{print $2}'`

	if [ "${IMAGE_NAME}" ==  "${IMAGE}" ] ; then
		echo "镜像已经运行 ${IMAGE_NAME}"
		exit 1							
	fi
	
	#修改镜像名称
    docker tag ${IMAGE} ${IMAGE}${OLD}	
	if [ $? -eq 0 ]; then
		echo "修改tag成功"
	else
		echo "修改tag失败"
		exit 1
	fi
	
	#停掉容器
	docker stop ${CONTAINER_ID}
	
	#删除容器
	docker rm ${CONTAINER_ID}
else
	#获取模块停止的容器id
	STOP_CONTAINER_ID=`docker ps -a | grep -w ${CONTAINER_NAEM} | awk '{print $1}'`
	if [ "${STOP_CONTAINER_ID}" !=  "" ] ; then
		STOP_IMAGE=`docker ps -a | grep -w ${CONTAINER_NAEM} | awk '{print $2}'`
		
		#修改镜像名称
		docker tag ${STOP_IMAGE} ${STOP_IMAGE}${OLD}	
		if [ $? -eq 0 ]; then
			echo "修改tag成功"
		else
			echo "修改tag失败"
			exit 1
		fi
		
		#删除容器
		docker rm ${STOP_CONTAINER_ID}
	fi
							
fi

#删除前一次保留的镜像
if [ "${OLD_IMAGES_TAG}" !=  "" ] ; then
	#获取前一次镜像id
	IMAGE_ID=`docker images | grep -w ${OLD_IMAGES_TAG} | awk '{print $3}'`
						
	#删除镜像	
	docker rmi -f ${IMAGE_ID}
fi


#运行镜像
echo "=====================运行镜像============================="

if [ "${PORT}" !=  "" ] ; then
	if [ "${MOUNT_PATH}" !=  "" ] ; then
		docker run -itd -p ${PORT}:${CONTAINER_PORT} --privileged=true -v ${MOUNT_PATH}:${CONTAINER_MOUNT_PATH} -v /etc/localtime:/etc/localtime --name  ${CONTAINER_NAEM} ${IMAGE_NAME}
	else
		docker run -itd -p ${PORT}:${CONTAINER_PORT} --privileged=true -v /etc/localtime:/etc/localtime --name  ${CONTAINER_NAEM} ${IMAGE_NAME}
	fi
else
	if [ "${MOUNT_PATH}" !=  "" ] ; then
		docker run -itd  --privileged=true -v ${MOUNT_PATH}:${CONTAINER_MOUNT_PATH} -v /etc/localtime:/etc/localtime --name  ${CONTAINER_NAEM} ${IMAGE_NAME}
	else
		docker run -itd  --privileged=true -v /etc/localtime:/etc/localtime --name  ${CONTAINER_NAEM} ${IMAGE_NAME}
	fi
fi

7.常见问题

当执行job任务时,出现不识别docker命令

1.确保系统中已经装好了docker,因为之前启动镜像时,我们是用本机的docker挂载进jenkins镜像中的

2.执行下方指令查询docker gid是否是996,之前打包jenkins时,设置的jenkins镜像dockergid是996

[root@localhost java]# cat /etc/group | grep docker
docker:x:996:

3.若不是996 则执行下方指令设置成996

groupmod -g 996 docker

流水线脚本ssh太复杂,不会写

1.先在配置里面点击下图按钮,会进入到流水线语法生成页面

docker镜像安装curl docker镜像安装tkinter_git_16

2.选择 SSH Publishers

docker镜像安装curl docker镜像安装tkinter_git_17

3.选择需要远程的服务器,我们之前在系统配置里面配置了blue服务器,接着在编写需要执行的命令

docker镜像安装curl docker镜像安装tkinter_docker_18