前端自动化部署

383 阅读1分钟

概览:

当推送代码时,触发git的webhooks钩子发送post请求,服务器启动一个serve来接收请求,收到请求后,git clone拉取更新代码,执行npm install ,npm build 更新页面。

webHooks

gitee.com/ 为例,在webhooks中添加url

image.png 添加后,当推送代码时,会发送一个post请求

Docker部分:

  1. 安装:docs.docker.com/get-docker/
  2. 使用镜像
"registry-mirrors": [
    "http://hub-mirror.c.163.com"
  ]

image.png 配置完后,右下角重启即可

3.Dockerfile,.dockerignore文件

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# .dockerignore
node_modules

上述两个文件放在/root目录下

node创建脚本index.js

创建js脚本文件,接收webhooks发送的请求,创建docker

const http = require("http")
const {execSync} = require("child_process")
const fs = require("fs")
const path = require("path")

// 递归删除目录
function deleteFolderRecursive(path) {
    if (fs.existsSync(path)) {
        fs.readdirSync(path).forEach(function (file) {
            const curPath = path + "/" + file;
            if (fs.statSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
}

const resolvePost = req =>
    new Promise(resolve => {
        let chunk = "";
        req.on("data", data => {
            chunk += data;
        });
        req.on("end", () => {
            resolve(JSON.parse(chunk));
        });
    });

http.createServer(async (req, res) => {
    console.log('receive request')
    console.log(req.url)
    if (req.method === 'POST' && req.url === '/') {
        const data = await resolvePost(req);
        const projectDir = path.resolve(__dirname,`./${data.repository.name}`)
        deleteFolderRecursive(projectDir)

        // 拉取仓库最新代码
        execSync(`git clone ${data.repository.git_ssh_url} ${projectDir}`, {
            stdio: 'inherit',
        })

        // 复制 Dockerfile 到项目目录
        fs.copyFileSync(path.resolve(__dirname,`./Dockerfile`), path.resolve(projectDir, './Dockerfile'))

        // 复制 .dockerignore 到项目目录
        fs.copyFileSync(path.resolve(__dirname,`./.dockerignore`), path.resolve(projectDir, './.dockerignore'))


        // 创建 docker 镜像
        execSync(`docker build -t ${data.repository.name}-image:latest .`, {
            stdio: 'inherit',
            cwd: projectDir
        })

        // // 拉取 docker 镜像
        // execSync(`docker pull yeyan1996/docker-test-image:latest`, {
        //     stdio: 'inherit',
        //     cwd: projectDir
        // })

        // 销毁 docker 容器
        execSync(`docker ps -a -f "name=^${data.repository.name}-container" --format="{{.Names}}" | xargs -r docker stop | xargs -r docker rm`, {
            stdio: 'inherit',
        })

        // 创建 docker 容器
        execSync(`docker run -d -p 8888:80 --name ${data.repository.name}-container ${data.repository.name}-image:latest`, {
            stdio: 'inherit',
        })

        console.log('deploy success')
    }
    res.end('ok')
}).listen(3000, () => {
    console.log('server is ready')
})
  • pm2 start index.js 后台启动;
  • pm2 lsit 查看列表
  • pm2 stop id 停止
  • pm2 log 查看日志
  • lsif -i:端口号 查看端口
  • kill -9 id 杀死进程 以上完成后,访问公网ip:8888会看到网页

参考资料:docker + webhook 从零实现前端自动化部署