手摸手教程:webhook + docker + nginx 打造简单的前后端项目ci/cd流程
前言
我是一个ci/cd知识的小白,然后自己人又菜,瘾又大,总想着弄个自己的网站项目,做点自己喜欢的东西放上去。但是不知道为啥,之前看的jenkins之类的方案,怎么都配不出来。然后摸索了好久,才做成了这个方案
流程
会有三个项目:一个前端项目、一个node后端项目、一个处理webhook请求的项目。大概流程就是前端或者后端项目的代码有更新,触发gitee(也可以用github)的webhook,重新构建项目
创建后端项目
1.初始化项目
mkdir back
npm init -y
2. package.json
{
"name": "back",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node ./server.js",
"stop": "pm2 stop vueback"
},
"keywords": [],
"author": "",
"license": "ISC"
}
2. server.js
let http = require('http');
let users = [{id:1,name:'kelvin1'},{id:2,name:'kelvin2'},{id:3,name:'kelvin3'}];
let server = http.createServer(function(req,res){
console.log(req.method,req.url);
if(req.url == '/api/users'){
res.setHeader('Access-Control-Allow-Origin','*'); // 防止跨域
res.end(JSON.stringify(users));
}else{
res.end('Now Found!');
}
});
server.listen(3000,()=>{
console.log('服务正在3000端口上启动!');
});
3. gitignore
node_modules
dockerignore
package-lock.json
4.Dockerfile
根目录创建Dockerfile文件
FROM node
LABEL name="back"
LABEL version="1.0"
COPY . /app
WORKDIR /app
RUN npm install
EXPOSE 3000
CMD npm start
5.dockerignore
根目录创建dockerignore文件。
.git
node_modules
package-lock.json
Dockerfile
.dockerignore
创建前端项目
1.安装脚手架生成项目(本地进行)
npm i @vue/cli -g
vue create front
cd client
npm i axios -S
2.App.vue
随便写点东西,跟后端服务项目交互
<template>
<ul>
<li v-for="(user) in users" :key="user.id">
{{user.id}}:{{user.name}}
</li>
</ul>
</template>
<script>
import axios from 'axios';
export default {
name: 'app',
data(){
return {
users:[]
}
},
mounted(){
axios.get('http://localhost:3000/api/users').then(response=>{
this.users = response.data;
});
}
}
</script>
<style>
</style>
3.Dockerfile
根目录创建Dockerfile文件
FROM nginx
LABEL name="front"
LABEL version="1.0"
COPY ./dist/ /usr/share/nginx/html/
COPY ./front.conf /etc/nginx/conf.d/
EXPOSE 80
4.front.conf
根目录创建front.conf文件。 try_files这里的配置就是前端项目history模式的nginx需要的配置。server_name这里写的是服务器的公网ip。location /api 这里就是配置代理后端接口
server {
listen 80;
server_name xxx.xxx.xxx.xxx;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://xxx.xxx.xxx.xxx:3000;
}
}
5.dockerignore
根目录创建dockerignore文件。
.git
node_modules
package-lock.json
Dockerfile
.dockerignore
webhook项目
nodemailer 插件用来发送邮件的,就是构建成功后发个邮件到指定的邮箱通知你。
初始化webhook项目
mkdir webhook
cd webhook
npm init -y
npm i nodemailer -S
npm i gitee-webhook-handler -D
2.webhook.js
新建webhook/webhook.js文件
var http = require('http')
var createHandler = require('gitee-webhook-handler')
let sendMail = require('./sendMail');
var handler = createHandler({ path: '/webhook', secret: '123456' }) // 123456 就是你在gihub或者gitee上写的secret密钥
function run_cmd(cmd, args, callback) {
var spawn = require('child_process').spawn;
var child = spawn(cmd, args);
var resp = "";
child.stdout.on('data', function(buffer) { resp += buffer.toString(); });
child.stdout.on('end', function() { callback (resp) });
}
handler.on('error', function (err) {
console.error('Error:', err.message)
})
handler.on('Push Hook', function (event) { // 该方法针对Gitee,这个地方就是GitHub 和 Gitee 不一样的地方,需要注意
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref);
let repositoryName = event.payload.repository.name
// 运行对应项目的脚本
run_cmd('sh', [`./${repositoryName}.sh`], function(text){
console.log(text, '开始发送邮件');
sendMail(`
<h1>部署日期: ${new Date()}</h1>
<h2>部署人: ${event.payload.pusher.name}</h2>
<h2>部署邮箱: ${event.payload.pusher.email}</h2>
<h2>提交信息: ${event.payload.head_commit&&event.payload.head_commit['message']}</h2>
`);
}); // 需要执行的脚本位置
})
try {
http.createServer(function (req, res) {
handler(req, res, function (err) {
res.statusCode = 404
res.end('no such location')
})
}).listen(4000) // 服务监听的端口,可以自行修改
}catch(err){
console.error('Error:', err.message)
}
3.sendMail.js
新建webhook/sendMail.js文件
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
// host: 'smtp.ethereal.email',
service: 'qq', // 使用了内置传输发送邮件 查看支持列表:https://nodemailer.com/smtp/well-known/
port: 465, // SMTP 端口
secureConnection: true, // 使用了 SSL
auth: {
user: 'xxx@qq.com', // 邮箱地址
pass: 'xxxxx', // 这里密码不是邮箱密码,是你设置的smtp授权码: 百度搜索下邮箱smtp授权码
}
});
function sendMail(message){
let mailOptions = {
from: '"JavaScript之禅" <xxxx@qq.com>', // 发送地址 该处邮箱为上面的发送邮箱地址。除了邮箱地址,其他随便写
to: 'xxxxx@163.com', // 接收邮箱
subject: '部署通知', // 邮件主题
html:message // 内容主体
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
});
}
module.exports = sendMail;
4.back.sh
新建webhook/back.sh文件。 ==注意:==back的名字可以自己改成需要,但是需要跟项目本身的名字一致吧
#!/bin/bash
WORK_PATH='/usr/projects/back'
cd $WORK_PATH
echo "清理代码"
git reset --hard origin/master
git clean -f
echo "拉取最新代码"
git pull origin master
echo "开始构建镜像"
docker build -t back .
echo "删除旧容器"
docker stop back-container
docker rm back-container
echo "启动新容器"
docker container run -p 3000:3000 --name back-container -d back
5.front.sh
新建webhook/front.sh文件。
#!/bin/bash
WORK_PATH='/usr/projects/front'
cd $WORK_PATH
echo "清理代码"
git reset --hard origin/master
git clean -f
echo "拉取最新代码"
git pull origin master
echo "打包最新代码"
npm run build
echo "开始构建镜像"
docker build -t front .
echo "删除旧容器"
docker stop front-container
docker rm front-container
echo "启动新容器"
docker container run -p 80:80 -d --name front-container front
6.package.json
为了避免关闭服务器命令窗口,脚本命令终端,加上pm2监控(pm2后面会在服务器配置时全局安装)
{
"name": "webhook",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "pm2 start ./webhook.js --name webhook --watch",
"stop": "pm2 stop webhook"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"gitee-webhook-handler": "^0.1.2",
"nodemailer": "^6.7.2"
}
}
7. gitignore
node_modules
package-lock.json
配置wenhook
上面三个项目建好后,推到gihub/gitee上。然后配置back以及front的webhook
配置服务器
我这边买的是腾讯云的服务器,centos系统,大家自行选择。
1.安装docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
2.阿里云加速
官方的镜像比较慢,换个阿里云的镜像
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}
EOF
# 重载所有修改过的配置文件
systemctl daemon-reload
systemctl restart docker
3.生成公钥并添加github
参考链接: github.com/settings/ke…
ssh-keygen -t rsa -b 4096 -C "xxx@163.com" // xxx这里填自己的邮箱吧
cat /root/.ssh/id_rsa.pub
4.安装git
yum install git -y
5.安装node、npm、pm2
使用nvm和nrm安装
# 从git 克隆nvm到本地的当前用户目录的nvm文件夹中
git clone git://github.com/creationix/nvm.git ~/nvm
# 把nvm添加到环境变量中
echo "source ~/nvm/nvm.sh" >> ~/.bashrc
source ~/.bashrc
nvm install --lts
npm i nrm -g
nrm use taobao
npm i pm2 -g
6.服务器上拉取三个项目代码
6.1 back项目
先不用启动,后续修改下代码既可以触发构建启动即可
git clone xxx.git
npm install
6.2 front
先不用启动,后续修改下代码既可以触发构建启动即可
git clone xxx.git
npm install
6.3 webhook
这个项目先开启
git clone xxx.git
npm install
npm run start
7.修改front和back的代码
重新push代码,触发webhook去构建。成功触发webhook构建的log(pm2 log命令查看)。然后服务器ip➕端口就可以正常访问构建好的项目了(当然,上面的项目的所有端口,都得在云服务器定义好外网防火墙)