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的界面,首次运行时,要等待一会时间,之后就会变成下方的页面
此时,需要输入一个初始管理员的密码,我们之前运行时,已经把jenkins的工作目录挂载到我们本地的/home/jenkins,输入以下指令得到密码。
cat /home/jenkins/secrets/initialAdminPassword
输入密码后,会出现安装插件的页面,我们这里选择安装推荐插件,等待安装结束
安装完插件后,会进入设置管理员的帐号,这里我们设置一个管理员帐号
设置完管理员帐号后,会提示配置jenkins的URL,这个url就是可以访问jenkins页面的,我们这边不变更
若是之前下载插件失败,有可能是网络原因导致,所以在提示我们是否重新在下时,直接跳过,进入到设置管理员帐号。
配置完成之后,既可以进入jenkins页面,由于之前插件下载有问题,我们在系统设置中,修改jenkins下载地址为国内地址。
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
4.添加gitee帐号,用于拉取代码使用
按照图示进行帐号添加,这个要记住我们设置的id,是用于拉取git代码的
5.配置jdk,maven环境变量,和ssh远程
在构建任务之前,必须要配置jdk和maven的环境变量,否则jenkins就会走默认的环境变量,导致发生异常
在添加环境变量之前,path的一定要加上path+xx,否则不会生效
配置ssh远程连接
这里现使用jenkins下载 Publish Over SSH 插件,接着在上图中拉到最下方,找到下图配置
6.创建一个job任务
流水线脚本
#!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.先在配置里面点击下图按钮,会进入到流水线语法生成页面
2.选择 SSH Publishers
3.选择需要远程的服务器,我们之前在系统配置里面配置了blue服务器,接着在编写需要执行的命令