什么是webhook
可以理解为Webhook是一个API概念,简单来说就是一种反向API机制,类似于触发器的一样。
近几年Webhook在前后端对接的开发模式中变得越来越流行,我们能用事件描述的事物越多,Webhook的作用范围也就越大。Webhook作为一个轻量的事件处理应用,正变得越来越实用。
无论是GitLab、GitHub、gitee都可以使用 git收到推送或者其他事件之后给指定服务器发送一个请求。
什么是Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。----百度百科。
个人理解其实docker就是更轻量,更便捷,更易于移植的虚拟机,我们的应用服务运行在他集成好一套虚拟环境,主要分为两个概念:
镜像(image) :类似操作系统镜像,docker创建虚拟环境需要基于一个docker镜像,镜像定义了系统需要什么初始的内容。
容器(container) :就是虚拟环境,基于image创建, 像一个虚拟机,实际上是一个进程,所以更轻量。
更多docker知识不再赘述,可自行了解。
流程架构图
安装docker
安装yum 工具包 设置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
docker重启
systemctl restart docker
配置阿里云加速
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
下载nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
. /root/.bashrc
nvm install stable
ssh-keygen -t rsa -b 4096 -C "xxxx@qq.com"
webhookjs
const http = require('http')
const crypto = require('crypto')
const {spawn} = require('child_process')//子进程
const SECRET = '123456'
const nodemailer = require('./nodemailer')
const sign = body => {
return 'sha1=' + crypto.createHmac('sha1', SECRET).update(body).digest('hex')
}
const app = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/webhook') {
const buffers = []
req.on('data', (buffer) => {
buffers.push(buffer)
})
req.on('end', (buffer) => {
const body = Buffer.concat(buffers)
const event = req.headers['x-github-event'] //push
const signature = req.headers['x-hub-signature']//签名 验证签名
if (signature !== sign(body)) {
return res.end('Not Found')
}
console.log('开始部署')
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({
ok: true
}))
if(event === 'push') {
const payload = JSON.parse(body.toString())
const child = spawn('sh', [`./${payload.repository.name}.sh`]);
const buffers = []
child.stdout.on('data', (buffer) => {
buffers.push(buffer)
})
child.stdout.on('end', (buffer) => {
let log = Buffer.concat(buffers).toString()
console.log('部署成功')
nodemailer(`
<h3>部署时间:${new Date()}</h1>
<h3>部署人: ${payload.pusher.name}</h1>
<h3>部署邮箱:${payload.pusher.email}</h1>
<h3>提交信息:${payload.head_commit.message}</h1>
<h4>部署日志:${log.replace('\r\n', '<br/>')}</h1>
`)
})
}
})
} else {
res.end('404 Not Found')
}
})
app.listen(4000, () => {
console.log('服务器已经启动,端口号:4000')
})
const nodemailer = require('nodemailer');
// async..await is not allowed in global scope, must use a wrapper
async function main(html) {
// Generate test SMTP service account from ethereal.email
// Only needed if you don't have a real mail account for testing
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
service: 'qq',
port: 587,
secure: true, // true for 465, false for other ports
auth: {
user: 'xxxxx@qq.com', // generated ethereal user
pass: 'xxxxx' // generated ethereal password//aqhsdqsypiaobiah
}
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: 'ヾ事过情迁 <247770359@qq.com>', // sender address
to: '247770359@qq.com', // list of receivers
subject: '部署通知', // Subject line
// text: 'Hello world?', // plain text body
html: html // html body
});
console.log('Message sent: %s', info.messageId);
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
}
module.exports = main
sh
#!/bin/bash
cd '/usr/projects/vue-front'
echo '先清除老代码'
git reset --hard origin/master
git clean -f
echo '拉去新代码'
git pull origin master
echo '安装node_modules'
npm install
echo '编译代码'
npm run build
echo '开始执行构建'
docker build -t vue-front:1.0 .
echo '停止旧容器&&删除旧容器'
docker stop vue-front-container
docker rm vue-front-container
echo '启动新容器'
docker container run -p 80:80 --name vue-front-container -d vue-front:1.0
Dockerfile
FROM nginx
LABEL name='yyx-vue-front'
LABEL version='0.0.1'
COPY ./dist /usr/share/nginx/html
COPY .vue.conf /etc/nginx/default.d
EXPOSE 80
conf
server {
listen 80;
server_name 139.198.174.89;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://139.198.174.89:3000;
}
}