首页 > 其他分享 >github-webhook+docker实现项目可持续自动化部署

github-webhook+docker实现项目可持续自动化部署

时间:2024-04-11 13:34:14浏览次数:24  
标签:github 项目 webhook vue 服务器 docker

目录

使用nginx+pm2+github-webhook+docker实现项目自动部署

注:docker也能实现pm2的守护进程功能(持续启动项目),所以使用了docker就不需要使用pm2了

但是需要注意的是使用node启动的webhook服务器不能使用docker,因为在webhook内部的sh脚本执行时需要到服务器的前后端项目文件中去执行,如果对webhook使用了docker,那么webhook所在的docker内不会存在前后端项目文件,所以webhook项目只能自己手动去服务器拉取启动,所以webhook项目使用pm2来管理

补充:

github-action+docker实现自动部署github-webhook+docker实现自动部署原理一样,但是实现步骤有区别:

github-action+docker实现自动部署的详细流程可以看我这篇文章:github-action+docker实现项目自动部署

(1)action是在github中的项目创建workflow工作流(yml脚本文件),yml脚本文件主要执行:

1、对仓库项目进行依赖下载及打包

2、根据项目创建的dockerfile文件生成docker镜像并将镜像push提交到腾讯云镜像仓库中

3、ssh登录腾讯云服务器pull提交的docker镜像并启动

上面的步骤执行完后push提交仓库代码会自动触发yml脚本文件完成自动部署

需要执行的包括创建yml脚本文件、dockerfile文件以及在github配置secret

(2)webhook是在github创建钩子,然后自己配置webhook服务器用于接收提交仓库代码的行为,然后在webhook服务器项目中新建.sh脚本文件用于触发webhook后对应在服务器中执行操作,包括下载项目依赖、打包项目,然后通过项目的dockerfile文件生成docker镜像并启动

webhook执行流程为push仓库代码后触发webhook钩子绑定的webhook服务器地址,执行自己定义的webhook服务器代码,然后根据代码会执行项目对应的sh脚本文件,会在服务器中下载项目依赖、打包项目、根据dockerfile创建docker镜像并启动

总结:action和webhook的原理一样,但是action更简便,不需要自己定义webhook服务器,而且还有一个不同在于action将项目下载依赖、打包项目、生成docker镜像放在了服务器外(github中)执行,而webhook把执行步骤都放在了服务器内执行

一、项目手动部署

在开始介绍自动部署之前,先看一下手动部署怎样实现的,以便于与自动部署进行对比:

1、本地项目上传到github仓库

2、xshell连接服务器,通过yum安装运行项目需要的环境(git、nvm)

# 安装git
yum install git -y

# 安装nvm
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

# 执行nvm命令
source /root/.bashrc

3、生成服务器对于github的ssh公钥并将公钥配置在github中,方便服务器拉取github代码

# 服务器生成ssh
ssh-keygen -t rsa -b 4096 -C "[email protected]"
# 查看生成的ssh公钥
cat /root/.ssh/id_rsa.pub

4、通过nvm安装node(npm),切换npm淘宝镜像源

# nvm安装node的最新稳定版本
nvm install stable

# 切换npm淘宝镜像源,使用cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org

5、通过yum安装yum-utils等yum工具、切换yum阿里源

# 安装yum工具
yum install -y yum-utils   device-mapper-persistent-data   lvm2
# 切换yum源
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

6、服务器新建/usr/projects目录存放项目代码,使用git clone将github的前后端项目代码克隆到该目录

mkdir /usr/projects
# 通过ssh拉取前端项目
git clone [email protected]:zhufengnodejs/vue-front.git
# 通过ssh拉取后端项目
git clone [email protected]:zhufengnodejs/vue-back.git

7、启动项目:切换到后端项目目录->cnpm i 下载依赖->npm run start启动项目(注意服务器开启端口号安全组)、启动前端项目步骤一样

cd /usr/projects/vue-back
# 下载后端项目依赖
cnpm i
# 启动项目
npm run start
# curl命令可以查看url显示的结果
curl http://119.3.102.56:3000/api/users

此时手动部署的项目在服务器断开后就不能访问了,而且本地修改代码后需要手动上传代码然后服务器拉取代码再安装依赖重新启动等,很麻烦

二、项目自动部署

介绍了手动部署项目的方式,再来看看怎样实现自动部署:

1、通过yum安装docker,服务器新建/etc/docker目录修改docker配置文件配置docker阿里云镜像源加速

(docker相当于一个镜像仓库,里面存放着很多镜像比如nginx、centos、包括自己配置的镜像空间存放单独的项目等,配置docker加速可以让docker下载这些镜像的速度加快)

(可以将前端和后端项目分别存放在单独的docker镜像空间中,一个docker镜像空间运行一个项目,下载的项目依赖的版本比如vue、node等互不冲突)

# 安装docker
yum install -y docker-ce docker-ce-cli containerd.io

# 配置docker阿里云镜像源加速
mkdir -p /etc/docker
# 执行命令向文件写入镜像源
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}
EOF
# 重载所有修改过的配置文件
systemctl daemon-reload
systemctl restart docker

2、在github项目的settings中的webhooks配置webhook服务器(前端项目和后端项目都需要配置)

(表示该项目提交到github上就会触发配置的webhook,会发请求到webhook配置的服务器上进行逻辑处理比如执行脚本等)

(注意配置的密码在github发请求时会在请求头以签名的形式传递过来,vue-webhook会验证该签名是否正确)

3、本地新建vue-webhook项目使用node开启该服务器用于接收github发来的请求(webhook.js)、

项目上传到仓库、

服务器clone代码到/usr/projects/vue-webhook、

服务器启动该项目

4、服务器通过npm下载pm2管理vue-webhook项目持续开启

(可以通过pm2 logs查看项目启动日志,通过pm2 flush清空日志)

(使用docker之后就可以不使用pm2管理node项目了,可以通过docker logs -f 容器名查看启动日志,容器启动失败就使用docker logs查看启动日志排错)

cnpm i pm2 -g

配置本地vue-webhook项目package.json文件的启动方式为pm2启动

{
  "scripts": {
    //pm2启动项目,--watch出现错误自动重启项目
    "start": "pm2 start ./webhook.js --watch --name='vue-webhook'",
    //停止项目
    "stop": "pm2 stop vue-webhook"
  },
}

上传更新的vue-webhook代码到仓库

服务器拉取vue-webhook仓库代码

5、配置自动构建后端项目:本地vue-webhook新增后端项目vue-back的自动构建脚本vue-back.sh(名字随便取)

(服务器执行该自动构建脚本可以自动拉取仓库代码并将该项目创建单独的docker空间存放并启动)

# vue-webhook/vue-back.sh

#后端项目自动构建配置
#!/bin/bash
WORK_PATH='/usr/projects/vue-back'
cd $WORK_PATH
# echo命令--语句打印输出在服务器
echo "清理代码"
git reset --hard origin/master
git clean -f
echo "拉取最新代码"
git pull origin master
echo "删除旧容器"
docker stop cha-node-container
docker rm cha-node-container
#删除旧镜像之前必须要先删除依赖镜像的容器
#删除旧镜像是为了旧镜像一直存在占用内存,后续可以思考不删除旧镜像,而是将新镜像修改版本号,旧镜像以老版本号继续存在
echo "删除旧镜像"
docker rmi cha-node:1.0.0
echo "开始构建新镜像"
# 执行到这里会执行后端项目配置的Dockerfile文件中的代码配置创建docker(注意要指定项目的版本号vue-back:1.0.0)
docker build -t vue-back:1.0.0 .
echo "启动新容器"
# 3000:3000代表将服务器主机的3000端口连接到docker内部项目启动的3000端口(访问服务器3000端口就会访问docker内部启动项目的3000端口)
docker container run -p 3000:3000 -d --name vue-back-container vue-back:1.0.0

其中自动创建一个docker镜像存放后端项目需要在后端项目vue-back中新建Dockerfile文件配置该项目的docker镜像空间(包括项目版本、docker内下载项目依赖包、项目启动端口号等)

# vue-back/Dockerfile

#配置后端项目的docker镜像空间(基于node镜像创建docker容器)
FROM node
LABEL name="vue-back"
#目前该项目版本号
LABEL version="1.0.0"
#将服务器下该项目下所有文件拷贝到docker的/app文件夹下
COPY . /app
WORKDIR /app
#docker中配置npm镜像源
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
#docker中安装项目依赖
RUN cnpm install
#项目端口号(docker对外暴露端口号)
EXPOSE 3000
#在docker中启动项目
CMD npm start

在vue-back后端项目中新建.dockerignore忽略文件,忽略不需要打包到项目的docker镜像空间中的文件

# vue-back/.dockerignore
.git
node_modules
package-lock.json
# 不把docker配置文件打包到docker中,配置文件只在创建docker时有用
Dockerfile
.dockerignore

6、配置自动构建前端项目:和上面构建后端项目步骤一样,但是配置代码不一样在vue-webhook项目新建vue-front.sh脚本,脚本配置不同点在于需要执行npm run build打包项目、

# vue-webhook/vue-front.sh

#前端项目自动构建配置
#!/bin/bash
WORK_PATH='/usr/projects/vue-front'
cd $WORK_PATH
echo "清理代码"
git reset --hard origin/master
git clean -f
echo "拉取最新代码"
git pull origin master
echo "下载项目依赖"
cnpm install
echo "打包最新代码"
npm run build
echo "删除旧容器"
docker stop cha-vue-container
docker rm cha-vue-container
echo "删除旧镜像"
docker rmi cha-vue:1.0.0
echo "开始构建新镜像"
docker build -t vue-front:1.0.0 .
echo "启动新容器"
docker container run -p 80:80 -d --name vue-front-container vue-front:1.0.0

再新建vue-front.conf配置前端项目的nginx(监听端口静态资源请求返回静态资源目录、动态资源请求反向代理到后端)(注意:这里的nginx不是服务器安装的nginx,而是前端项目docker空间中安装的nginx)、

# vue-front/vue-front.conf
# 前端项目的nginx配置
server{
    listen 80;
    server_name 119.3.102.56;
    # 静态资源请求
    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    # 动态资源请求使用反向代理
    location /api {
        proxy_pass http://119.3.102.56:3000;
    }
}

在vue-front项目新建Dockerfile文件配置前端项目的docker镜像(配置自动将打包后的前端项目dist目录放在nginx静态资源目录下,将前端vue-front.conf配置文件放在nginx配置目录下)、

# vue-front/Dockerfile

# nginx服务器
FROM nginx
LABEL name="vue-front"
LABEL version="1.0.0"
# 将打包后的dist文件夹下的文件拷贝到docker中的nginx静态资源文件夹目录html下
COPY ./dist/ /usr/share/nginx/html/
# 将前端nginx配置文件拷贝到docker中的nginx子配置文件夹目录下
COPY ./vue-front.conf /etc/nginx/conf.d/
# 前端项目docker对外暴露端口号设置为80
EXPOSE 80

再新建.dockerignore配置忽略文件

# vue-front/.dockerignore

.git
node_modules
package-lock.json
Dockerfile
.dockerignore

7、在本地vue-webhook项目中的webhook.js文件中处理接收到github传来的触发仓库项目上传操作的请求(即配置了webhook的项目有上传操作)

(处理请求包括验证github请求的请求头中的签名是否正确、验证是否为push操作、如果满足条件开启进程执行sh命令,即sh执行对应有上传仓库操作的项目的脚本(.sh),执行该脚本后会将该项目自动拉取仓库最新代码并刷新该项目的docker并下载依赖后启动该项目)

// vue-webhook/webhook.js

const http = require('http')
let crypto = require('crypto');
//开启进程
var spawn = require('child_process').spawn;
let sendMail = require('./sendMail');
//在github上配置webhooks时输入的secret
const SECRET = '123456';
//配置数据加密方法
function sign(data) {
    return 'sha1=' + crypto.createHmac('sha1', SECRET).update(data).digest('hex')
}
​
const server = http.createServer((req, res) => {
    console.log('------------分割线开始-------------');
    console.log('方法:', req.method, '路径:', req.url);
​
    if (req.method === 'POST' && req.url == '/webhook') {
        console.log('请求成功');
        let buffers = [];
        //接收github传递的数据(请求体)
        req.on('data', function (data) {
            console.log('接收github请求体数据');
            buffers.push(data);
        });
        req.on('end', function () {
            console.log('接收github请求体数据完成');
            let body = Buffer.concat(buffers);
            //获取github传递过来的请求头信息
            let sig = req.headers['x-hub-signature'];
            let event = req.headers['x-github-event'];
            let id = req.headers['x-github-delivery'];
            //判断github传递的签名是否符合要求
            if (sig !== sign(body)) {
                console.log('签名验证失败-签名不正确');
                console.log('github签名:', sig, '自己的签名:', sign(body))
                return res.end('Not Allowed');
            }
            console.log('签名验证成功-签名正确');
            res.setHeader('Content-Type', 'application/json');
            res.end(JSON.stringify({ "ok": true }));
            //判断是否是push项目到仓库
            if (event === 'push') {
                console.log('push代码到仓库操作执行');
                let payload = JSON.parse(body);
                //开启进程处理执行对应项目的脚本(第一个参数是命令,第二个参数是文件名)
                console.log(`开始执行脚本文件${payload.repository.name}.sh`);
                let child = spawn('sh', [`./${payload.repository.name}.sh`]);
                let buffers = [];
                //获取执行脚本的进程传递回来的信息(项目构建部署信息)
                child.stdout.on('data', function (buffer) { buffers.push(buffer) });
                child.stdout.on('end', function () {
                    let logs = Buffer.concat(buffers).toString();
                    console.log('获取到执行脚本传递回来的信息');
                    //将部署信息整合发邮件通知
                    sendMail(`
                        <h1>部署日期: ${new Date()}</h1>
                        <h2>部署人: ${payload.pusher.name}</h2>
                        <h2>部署邮箱: ${payload.pusher.email}</h2>
                        <h2>提交信息: ${payload.head_commit && payload.head_commit['message']}</h2>
                        <h2>布署日志: ${logs.replace("\r\n", '<br/>')}</h2>
                    `);
                });
            }
        })
​
    } else {
        res.end('Not Found!');
    }
})
​
server.listen(4000, () => {
    console.log('webhook on 4000....');
})

vue-webhook项目中新建sendEmail.js文件配置发邮件的代码,然后配置webhook.js代码在自动化构建成功后调用sendEmail.js的函数发邮件告知部署信息

// vue-webhook/sendEmail.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: '[email protected]',
        // 这里密码不是qq密码,是你设置的smtp授权码
        pass: 'jjthfwzqjsimejfj',
    }
});
​
​
function sendMail(message) {
    console.log('开始发邮件');
    let mailOptions = {
        from: '"1776875119" <[email protected]>', // 发送地址
        to: '[email protected]', // 接收者
        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);
        console.log('------------分割线结束-------------');
    });
}
module.exports = sendMail;

上传vue-webhook项目到仓库、

服务器拉取vue-webhook项目并启动该项目(即启动该项目接收github请求并执行对应项目的脚本实现对应项目的自动构建及部署)

cd /usr/projects/vue-webhook
git pull origin master
cnpm i
# 启动项目(pm2)
npm start
# 查看pm2启动该项目打印的日志
pm2 logs
自动构建部署流程

以前端代码举例,本地修改了前端代码后将代码上传到github仓库,由于该前端项目的仓库配置了webhooks,github监听到上传操作就会发请求到配置webhooks时填写的url(即vue-webhook项目启动的node服务),服务器的vue-webhook接收到github请求就会验证github请求及签名等(验证安全),验证通过就会执行对应前端项目的脚本文件(在服务器执行sh 前端脚本.sh命令),脚本文件会下将仓库代码pull下来,在脚本文件执行到创建docker时就会执行前端项目的Dockerfile文件将项目添加到docker并下载所需环境及依赖后启动前端项目,项目部署成功后会将部署信息以邮件的形式通知我

上面的流程执行完后的效果就是本地修改代码并上传到仓库后,收到邮件通知则代表项目自动构建及部署完成,可以直接访问url查看上传到仓库代码的最新效果

docker概念补充

1、服务器安装docker后,可以创建多个docker容器,每个docker容器相当于一个小的操作系统,每个docker容器中可以安装不同的镜像(nginx、node等),通过这些镜像组成一个项目运行环境,每个docker容器内部自成一个独立的环境,互不影响,比如可以通过nginx镜像为前端项目创建一个docker容器,通过node镜像为后端创建一个docker容器,然后分别在各自的docker容器中启动项目,将启动的docker的端口号对应到服务器主机的端口号,这样外界就可以正常访问了

2、docker这样启动多个容器,不同容器内部有不同的环境,可以解决不同环境(比如node版本不同等)的项目运行在单一环境的服务器出现错误的情况,可以将不同的项目分别创建对应的docker容器,在容器中配置对应的环境,然后在服务器中启动

3、在仓库拉下项目代码后通过Dockerfile文件构建项目的docker容器(在docker内部配置该项目所需环境并启动),就可以不用担心项目运行的环境和本地/服务器的环境不同而报错的问题

4、docker可以通过docker ps查看启动的容器,然后可以通过docker exec -it 容器名 /bin/bash进入容器内部,通过exit退出进入的容器,进入到容器内部会发现容器内部相当于一个小的linux系统,该有的文件夹都有(/etc、/usr等),nginx一样的是下载到etc/nginx里面,nginx静态资源目录也是在/usr/share/nginx/html里面,就是说每一个docker容器内部都是一个完整的linux系统,可以像在linux系统下载或操作文件一样在容器内部进行操作

标签:github,项目,webhook,vue,服务器,docker
From: https://blog.csdn.net/minusing/article/details/137413405

相关文章

  • Docker常用命令(傻瓜式笔记)
    话不多说,跟我学习Docker常用命令!Docker#查看内核uname-r#启动dockersystemctlstartdocker#查看docker状态systemctlstatusdocker#重启dockersystemctlrestartdocker#查看版本dockerversion#查看信息dockerinfo#获取帮助docker--help#查......
  • Docker安装Nginx容器
    安装Nginx#查找官方镜像dockersearchnginx#下载最新版Nginx镜像(其实此命令就等同于:dockerpullnginx:latest)dockerpullnginx#下载指定版本的Nginx镜像(xxx指具体版本号)dockerpullnginx:xxx#检查当前所有Docker下载的镜像dockerimages创建Nginx配置......
  • docker-compose部署kafka
    docker-compose.ymlversion:'2'services:zookeeper:image:develop-harbor.geostar.com.cn/3rd/zookeeper:3.5.5ports:-"2181:2181"kafka:image:develop-harbor.geostar.com.cn/3rd/wurstmeister/kafka:2.12-2.2.1......
  • 在linux中迁移Docker默认镜像存储路径解决磁盘空间满的问题
    通过yum或者apt安装的docker通常数据存储在/var/lib/docker/,包括镜像、运行数据等。然而这个目录是在根目录下面,容易导致系统盘满了。如果出现这种情况就需要迁移docker的默认目录。以下基于此说明。本文使用到的docker版本为DockerVersion:24.0.5,宿主机为CentOS7。不......
  • 使用docker部署基于selenium和chrome-headless的爬虫
    使用docker部署基于selenium和chrome-headless的爬虫无论是测试还是爬虫的一些工作,有时候都会用到selenium去对chrome执行自动化操作,这里介绍一下如何使用docker快捷方便的部署相关应用。1.selenium+chrome镜像通过dockersearchselenium我们发现,有一个docker镜像叫做sele......
  • 记录很久没用Ubuntu遇到的问题,并安装vulhub漏洞环境(Docker已装好)
    前景提要:之前有装过vulhub,但是今天想复现一下shiro反序列化漏洞(CVE-2016-4437),查看我下载的vulhub,没有找到。就打算更新(顺便提一嘴,更新命令为:gitpull,要先关闭docker),但是我一更新就VMware就弹出“对文件“……\VirtualMachines\Ubuntu64位\Ubuntu64位-000001.vmdk”的操作失......
  • Docker常用命令个人学习心得
    Docker的常用命令涵盖了容器的创建、管理、镜像的下载与推送等多个方面。1、镜像管理dockerps:列出所有正在运行的容器。dockerps-a:显示所有的容器,包括未运行的。dockertag[现有镜像名]:[现有标签][新镜像名]:[新标签]:为现有的镜像创建一个新的标签。dockerrmi[image......
  • GitHub问题解决新突破,复旦大学MAGIS框架大幅超越GPT-4
    获取本文论文,请关注公众号【AI论文解读】回复:&nbsp;论文解读引言:GitHub问题解决的挑战与LLMs的潜力在软件开发的演进过程中,解决GitHub仓库中出现的问题是一个复杂的挑战。这不仅涉及到新代码的加入,还要维护现有功能的稳定运行。大型语言模型(LLMs)在代码生成和理解方......
  • docker -nginx
                (版本号)dockerpullnginx:1.17.8dockerrun--namenginx-p9091:80-dnginx:1.17.8mkdir-p/data/nginx/{conf,conf.d,html,logs}##拷贝配置文件dockercp1022c6f181b9:/etc/nginx/nginx.conf/data/nginx/conf/nginx.conf##映射......
  • 让 GitHub 仓库的代码占比统计中包含 Markdown 文件 开发 Git 命令行 个人知识管理 知
    tags:网站/GitHub开发/Git命令行/git个人知识管理/知识库知识领域/文档工程让GitHub仓库的代码占比统计中包含Markdown文件GitHub是一个基于web的版本控制和协作平台,主要用于存储、管理和分享开源代码和项目。它支持Git作为唯一的版本库格式,使得多个开发者可......