1.前期准备
安装必要的jenkins插件:
- NodeJS plugin : vue项目打包必须插件,安装后才能在系统设置里面配置安装nodejs环境
- Pipeline : jenkins初始化的时候会默认安装
- Publish Over SSH : 因为我们要发往远程服务器,所以要装,如果本地docker运行项目,则不需要这个插件
- Blue Ocean : 蓝海了,UI插件,选装,安装后访问地址:【jenkins地址】/blue
2.配置jenkins
2.1 安装nodejs环境
进入Manage Jenkins -> Configure Tools找到 NodeJS(安装了NodeJS plugin插件才有这项)
NodeJS主要配置如下:
别名:自定义,这个很重要,后面配置pipeline文件时需要
选择 Install from nodejs.org,实测下载速度也还可以接受
版本自己选择需要的版本
2.2 配置SSH
进入Manage Jenkins -> Configure System找到 Publish over SSH(安装了Publish Over SSH插件才有这项)
SSH Servers主要配置如下:
SSH Server Name: ssh配置名称(自定义)记住这个名称,pipeline代码中要用到
Hostname: 主机IP
Username: ssh账户名
Remote Directory: 远程路径,可以理解为ssh连接上后自动cd到目录
port: ssh端口,一般默认为22
Proxy password: ssh密码
⚠️ 注意
我这里使用的是在docker中运行jenkins,如果宿主机有maven环境直接配置到jenkins里面肯定用不了,需要用docker的数据卷 -v 挂载到jenkins里面才可以访问。
3.新建Item
3.1 进入jenkins主界面新建Item
- 这里简略直接新建构建功能,实际情况下可能要新建文件夹来对项目进行分类
3.2 选择流水线(Pipeline)
3.3 General配置
- 选择丢弃旧的构建(最好配置一下,防止占机器磁盘)
策略: Log Rotation
保持构建的天数: 不设置
保持构建的最大个数: 视情况设置
流水线(Pipeline)配置
- 定义:选择 Pipeline script 或者 Pipeline script from SCM
Pipeline script: 需要在jenkins里面写pipeline脚本
Pipeline script from SCM: 需要在项目一级目录下新建 Jenkinsfile 文件,再将pipeline脚本写在里面,这种方式相较于上面那种方式,需要多如下配置:
勾选 Pipeline script from SCM 后,配置
SCM: 选择git
Repository URL: 代码仓库地址
Credentials: git账户密码密钥的ID,在Manage Jenkins->Manage Credentials里面可以找到,没有的话,就新增一个
Branches to build: 选择代码分支
脚本路径: 默认Jenkinsfile,需要跟项目一级目录下的pipeline脚本文件名一样,建议和默认保持一样
# 其他没提到的设置保持默认吧
我这里选择的是 Pipeline script ,因为觉得把拉取代码也集成到pipeline脚本里统一管理好一点,没有割裂感
脚本如下,视情况改一下:
def gitUrl = '【改成你的代码仓库地址】'
// maven的默认安装地址
def project = '【改成你的项目名称】'
def env ='【改成你的项目环境,一般为.xxx.development文件】'
def port = '【改成你的项目端口号】'
def proxy_port = '【改成你的项目映射到docker宿主机的端口号】'
def deploy_home = '【改成你的远程服务器上部署的目录】'
def branch = '【改成你的代码分支】'
// 保存在jenkins凭据中的凭据ID
def credentialsId = '【改成你存在jenkins里面的代码仓库账号密码凭据ID】'
def remoteId = '【改成你的ssh服务器设置ID,对应2.1里面的SSH Server Name】'
pipeline {
agent any
stages {
stage('代码更新'){
steps {
git branch: "$branch",credentialsId: "$credentialsId",url: "$gitUrl"
}
}
stage('项目构建'){
steps {
# Nodejs18.8.0即为前面配置的nodejs环境取得别名
nodejs("Nodejs18.8.0"){
sh 'node --version'
sh 'npm --version'
sh 'npm install'
sh 'npm run build:prod'
}
}
}
stage('生成Dockerfile'){
steps {
// 动态生产dockerfile
sh """
echo '''
# 基础镜像使用Nginx
FROM nginx:latest
MAINTAINER xxx
ENV TimeZone=Asia/Shanghai
ADD /dist/ /usr/share/nginx/html/
EXPOSE 80
''' > Dockerfile
"""
}
}
stage('生成Nginx配置文件'){
steps {
// 动态生产Nginx.conf
sh """
echo '''
server {
listen 80;
listen [::]:80;
server_name 宿主机IP;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
''' > default.conf
"""
}
}
stage('生成deploy.sh'){
steps {
// 动态生产dockerfile
sh """
echo '''
#!/bin/bash
#项目占用端口
APP_PORT=$port
APP_PROXY=$proxy_port
# 项目名字
APP_NAME=$project
# 项目根目录
APP_HOME=$deploy_home/$project
# 项目日志输出目录
APP_LOG_OUT=$deploy_home/logs
# 镜像的tag
APP_TAG=1.0
mkdir -p \${APP_HOME}
mkdir -p \${APP_LOG_OUT}
echo "清理已有容器及镜像资源"
docker stop \${APP_NAME} && docker rm \${APP_NAME}
echo "清理已有容器及镜像资源成功!!!!"
echo "镜像制作"
docker build -t \${APP_NAME}:\${APP_TAG} .
echo "镜像制作完成"
echo "开始运行"
docker run -d --name \${APP_NAME} -p \${APP_PROXY}:80 -v \${APP_LOG_OUT}:/var/log/nginx -v \${APP_HOME}/default.conf:/etc/nginx/conf.d/default.conf \${APP_NAME}:\${APP_TAG}
echo "已成功运行"
''' > deploy.sh
"""
}
}
stage('打包文件'){
steps{
sh """
rm -rf deploys
mkdir deploys
ls
cp -r $project_home deploys/
mv Dockerfile deploys/
mv deploy.sh deploys/
mv default.conf deploys/
tar -zcvf deploys.tar.gz deploys/
rm -rf deploys
mv deploys.tar.gz $project_home/
"""
}
}
stage('发往远程'){
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: """$remoteId""", transfers: [sshTransfer(cleanRemote: false, excludes: '',
execCommand: """
echo '准备解压发布文件并部署'
cd $deploy_home/$project
#解压到当前目录,并去除一级目录
tar -zxvf deploys.tar.gz --strip-components 1
rm -rf deploys.tar.gz
sh deploy.sh
echo '部署成功'
""",
execTimeout: 120000,
flatten: false,
makeEmptyDirs: false,
noDefaultExcludes: false,
patternSeparator: '[, ]+',
remoteDirectory: """/$project""",
remoteDirectorySDF: false,
removePrefix: """$project_home""",
sourceFiles: """$project_home/deploys.tar.gz""")],
usePromotionTimestamp: false,
useWorkspaceInPromotion: false,
verbose: false)])
}
}
stage('删除中间文件'){
steps {
sh """
cd $project_home
rm -rf deploys.tar.gz
"""
}
}
}
post {
success {
println('项目发布成功!')
}
failure {
println('项目发布失败!')
}
}
}
如果是Pipeline script from SCM方式,脚本里面省去拉去代码的步骤即可
脚本的核心流程是:
- 拉取代码
- npm 构建项目
- 生成Dockerfile
- 生成nginx的default.conf文件,用以替换nginx镜像自带的default.conf文件
- 生成deploy.sh
- 将Dockerfile,deploy.sh,default.conf和项目build后的文件压缩成压缩包
- 将文件发往远程服务器,并在远程服务器解压文件,执行deploy.sh
- deploy.sh执行后,会根据Dockerfile将项目包构建成docker镜像,并运行
部署成功后,项目挂载在宿主机的proxy_port端口,映射到镜像的80端口
直接访问
http://[IP]:8081
即可,注意宿主机的防火墙记得开启,防止端口被防火墙拦截