巧用GitHub的CICD功能免费打包部署前端项目

近年来,随着前端技术的发展,前端项目的构建和打包过程变得越来越复杂,占用的资源也越来越多。我有一台云服务器,原本打算使用Docker进行部署,以简化操作流程。然而,只要执行sudo docker-compose -f deploy/docker-compose/docker-compose.yaml up命令,服务器就直接卡死,CPU占用率飙升至100%,导致我无法正常使用。

经过一番思考和尝试,我决定借助GitHub的CICD功能来解决这个问题。通过利用免费的GitHub的服务器资源,我可以只将打包好的文件部署到我的后台服务器上,简直不要太方便啦!下面详细介绍具体步骤。

背景

在使用Docker进行前端项目和后端服务的部署时,我遇到的问题主要出在资源占用上。由于我的云服务器配置较低,同时执行多个Docker容器的构建和启动指令,导致服务器资源被瞬间耗尽。因此,我决定寻找一种更高效的方式来完成前端项目的构建和打包,而无需占用本地服务器的大量资源。GitHub的CICD功能恰好可以满足这一需求,它提供了一个强大的云端构建环境,可以轻松地完成项目的构建和打包工作。
在这里插入图片描述

准备工作

  1. GitHub账户:确保你有一个GitHub账户,并且已经创建了一个仓库来存放你的前端项目代码。
  2. 部署服务器:准备好你的部署服务器,确保服务器可以访问GitHub,并且已经做好了相应的部署准备工作。
  3. SSH密钥:为GitHub配置SSH密钥,以便能够通过SSH连接到你的部署服务器。

步骤

1. 编写Dockerfile

首先,确保你的前端项目有一个Dockerfile,用于构建前端项目的镜像。以下是一个简单的Dockerfile示例:

# 使用官方Node镜像作为构建环境
FROM node:20-slim AS build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build# 使用官方Nginx镜像作为运行环境
FROM nginx:alpine AS production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

2. 创建GitHub Actions Workflow

在GitHub仓库中创建一个.github/workflows文件夹,然后在文件夹中创建一个YAML文件,例如ci-cd.yml。这个文件将定义GitHub Actions的工作流程。

name: CI/CD for Frontend Projecton:push:branches:- mainjobs:build:runs-on: ubuntu-lateststeps:- name: Checkout codeuses: actions/checkout@v4- name: Set up Node.jsuses: actions/setup-node@v4with:node-version: '20'- name: Install dependenciesrun: npm install- name: Run build scriptrun: npm run build- name: Upload build artifactsuses: actions/upload-artifact@v4with:name: frontend-buildpath: ./distdeploy:needs: buildruns-on: ubuntu-lateststeps:- name: Download build artifactsuses: actions/download-artifact@v4with:name: frontend-buildpath: ./dist- name: Deploy to serveruses: appleboy/scp-action@masterwith:host: ${{ secrets.SERVER_HOST }}username: ${{ secrets.SERVER_USERNAME }}password: ${{ secrets.SERVER_PASSWORD }}port: ${{ secrets.SERVER_PORT }}source: "dist"target: "/root/build"

3. 配置GitHub Secrets

在GitHub仓库设置中,配置以下Secrets:

  • SERVER_HOST:你的服务器IP地址
  • SERVER_USERNAME:你的服务器用户名
  • SERVER_PASSWORD:你的服务器密码
  • SERVER_PORT:你的服务器SSH端口(默认为22)

这些Secrets用于在GitHub Actions Workflow中安全地存储和使用敏感信息,如服务器的登录凭证。

4. 配置服务器

确保服务器已经配置好Nginx,并且可以通过SSH访问。将前端项目的构建输出目录(例如dist)上传到服务器后,Nginx需要配置为指向这个目录以提供静态文件服务。

5. 下载构件

当工作流运行完成后,构建好的前端文件会被上传为构件。可以在 GitHub 项目的 Actions 标签下找到对应的运行记录,并下载构件。具体操作如下:

  1. 打开GitHub 项目页面,在左侧菜单中点击 Actions
  2. 找到触发的构建工作流,点击对应的运行记录。
  3. 在运行记录页面的右上角,会看到 Artifacts 标签,点击它。
  4. 点击上传的构件名称(如 frontend-build),就可以开始下载。

6. 自动化部署到后台服务器

为了进一步提升效率,可以借助 scprsync 将构件从 GitHub Actions 自动部署到云服务器。这里以 scp 为例,需要配置 SSH 密钥,并在 GitHub Secrets 中设置服务器的访问凭据。

配置 SSH 密钥
  1. 在本地生成 SSH 密钥对(如果还没有的话),使用命令 ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
  2. 将生成的公钥添加到云服务器的 ~/.ssh/authorized_keys 文件中。
  3. 将私钥添加到 GitHub 项目的 Secrets 中,设置为 SSH_PRIVATE_KEY
修改工作流文件以支持自动部署

build.yml 文件中添加部署步骤:

- name: Install SSH Clientuses: webfactory/ssh-agent@v0.5.4with:ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}- name: Deploy to Remote Serverrun: |scp -r ./build user@your_server_ip:/path/to/deploy

确保将上述命令中的 useryour_server_ip/path/to/deploy 替换为你的服务器用户名、服务器 IP 地址和你想部署到的路径。
在这里插入图片描述

为了使上述命令能够顺利执行,需要在GitHub仓库的“Settings” -> “Secrets”中添加SSH_PRIVATE_KEY和服务器的IP地址等信息,将本地生成的私钥内容复制到该Secret中。
在这里插入图片描述

总结需要确认以下三点:

  • 确认公钥已经正确添加到云服务器的~/.ssh/authorized_keys文件中。
  • 在GitHub仓库的“Settings” -> “Secrets”中添加SSH_PRIVATE_KEY。将本地生成的私钥内容复制到该Secret中。
  • 添加SERVER_IP,将你的云服务器的IP地址添加到该Secret中。

通过上述步骤,利用 GitHub Actions 的免费 CI/CD 资源编译打包前端项目,并将结果自动部署到你的云服务器上,无需占用本地服务器的资源。这样不仅提高了效率,还简化了部署流程,太美啦。

注: 在使用 GitHub Actions 实现 CI/CD 自动化部署时,将生成的公钥添加到云服务器的 ~/.ssh/authorized_keys 文件中是推荐的做法,这样可以实现无密码的自动化部署。这样 GitHub Actions 在执行部署时就可以使用私钥进行身份验证,而无需每次都输入密码。这不仅提高了部署的效率,也增强了安全性,因为私钥的存储和使用可以被更好地控制。
在这里插入图片描述

结论

通过GitHub的CICD功能,我们可以利用其强大的云端构建环境来完成前端项目的构建和打包工作,而无需占用本地服务器的大量资源。这样不仅可以提高构建效率,还可以降低服务器的负担,使我们的开发和部署过程更加流畅。

附:我的Dockerfile:

# 如果需要用 cicd ,请设置环境变量:
# variables:
#     DOCKER_BUILDKIT: 1FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /appFROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prodFROM base AS build
COPY --from=prod-deps /app/node_modules /app/node_modules
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install && pnpm run buildFROM nginx:alpine
LABEL MAINTAINER="bypanghu@163.com"
COPY --from=base  /app/.docker-compose/nginx/conf.d/my.conf /etc/nginx/conf.d/my.conf
COPY --from=build  /app/dist /usr/share/nginx/html
RUN ls -al /usr/share/nginx/html

我的docker-compose.yaml文件:

version: "3"# 声明一个名为network的networks,subnet为network的子网地址,默认网关是177.7.0.1
networks:network:ipam:driver: defaultconfig:- subnet: '177.7.0.0/16'# 设置mysql,redis持久化保存
volumes:mysql:redis:services:web:build:context: ../../webdockerfile: ./Dockerfilecontainer_name: gva-webrestart: alwaysports:- '8080:8080'depends_on:- servercommand: [ 'nginx-debug', '-g', 'daemon off;' ]networks:network:ipv4_address: 177.7.0.11server:build:context: ../../serverdockerfile: ./Dockerfilecontainer_name: gva-serverrestart: alwaysports:- '8888:8888'depends_on:mysql:condition: service_healthyredis:condition: service_healthylinks:- mysql- redisnetworks:network:ipv4_address: 177.7.0.12mysql:image: mysql:8.0.21       # 如果您是 arm64 架构:如 MacOS 的 M1,请修改镜像为 image: mysql/mysql-server:8.0.21container_name: gva-mysqlcommand: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci #设置utf8字符集restart: alwaysports:- "13306:3306"  # host物理直接映射端口为13306environment:#MYSQL_ROOT_PASSWORD: 'Aa@6447985' # root管理员用户密码MYSQL_DATABASE: 'qmPlus' # 初始化启动时要创建的数据库的名称MYSQL_USER: 'gva'MYSQL_PASSWORD: 'Aa@6447985'healthcheck:test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "gva", "-pAa@6447985"]interval: 10stimeout: 5sretries: 3volumes:- mysql:/var/lib/mysqlnetworks:network:ipv4_address: 177.7.0.13redis:image: redis:6.0.6container_name: gva-redis # 容器名restart: alwaysports:- '16379:6379'healthcheck:test: ["CMD-SHELL", "redis-cli ping | grep PONG || exit 1"]interval: 10stimeout: 5sretries: 3volumes:- redis:/datanetworks:network:ipv4_address: 177.7.0.14

最后,附上我的cicd脚本代码(测试ok,完全可用):
.github\workflows\ci-cd.yml

name: CI-CD Build and Deploy Frontendon:push:branches: [ main ]pull_request:branches: [ main ]jobs:build:runs-on: ubuntu-lateststrategy:matrix:node-version: [20.x]steps:- uses: actions/checkout@v4- name: set Node.js versionuses: actions/setup-node@v4with:node-version: ${{ matrix.node-version }}- name: cache Node.js moduleuses: actions/cache@v4with:path: ~/.npmkey: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}restore-keys: |${{ runner.os }}-node-- name: install dependenciesrun: npm install- name: Create build directoryrun: mkdir -p ./dist- name: Build projectrun: npm run build- name: upload Artifactuses: actions/upload-artifact@v4with:name: build resultpath: ./dist- name: Install SSH clientrun: sudo apt-get install -y openssh-client- name: Create a text file for testingrun: touch ./dist/text.txt- name: Set up SSH keysrun: |mkdir -p ~/.sshecho "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_ed25519chmod 600 ~/.ssh/id_ed25519ssh-keyscan -t ed25519 120.27.146.247 >> ~/.ssh/known_hostsenv:SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}- name: Deploy to Remote Serverrun: |scp -r ./dist root@120.27.146.247:/root/buildenv:SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}

参考资料

  • GitHub Actions
  • Docker Compose
  • SCP Action

:文中提到的docker-compose.yaml内容,主要用于本地开发环境的构建和部署,可以按照实际需求进行调整。在CICD流程中,我们主要是利用Docker来构建前端项目的镜像,然后将构建好的静态文件通过SCP方式上传至部署服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python之装饰器二 带参数的装饰器

前言一、带参数的装饰器二、在装饰器里面传入参数总结 前言 暂无 一、带参数的装饰器 我们知道,不带参数的装饰其实就是在函数的头上添加装饰器时放一个名称,这种写法就默认了装饰器函数调的是被装饰函数自己,换句话说就是,大家…

Windows 主机与安卓设备网线直连配置教程

在一些特殊场景下,我们可能需要在 Windows 主机没有联网的情况下,与安卓设备通过网线直连进行通信。本文将详细介绍具体的配置步骤。 一、硬件准备 一根网线(直通线或交叉线,具体取决于设备接口)。 一台支持以太网连…

Linux文件系统与磁盘存储

目录 一、磁盘基础 二、磁盘的结构与工作原理 1. 磁盘的物理结构 2. 磁盘的工作原理 🍒磁道与扇区 : 🍇磁盘如何找数据? 3. 磁盘的应用场景 🌵个人电脑 🌻公司服务器 4. 逻辑块地址(LB…

进程线程的创建、退出、回收

1. 进程相关知识点 1.1 进程创建 fork(): 功能:创建一个子进程。 返回值: 父进程中返回子进程的 PID。 子进程中返回 0。 失败返回 -1。 特点:子进程是父进程的副本,拥有独立的内存空间。 vfork():…

解耦的艺术_应用架构中的解耦

文章目录 Pre解耦的技术演化应用架构中的解耦小结 Pre 解耦的艺术_通过DPI依赖倒置实现解耦 解耦的艺术_通过中间层映射实现解耦 解耦的技术演化 技术的演化史,也是一部解耦的历史。从最初的面向对象编程(OOP)到Spring框架的依赖注入&…

低概率发生调用`pthread_cond_wait`的线程没有被唤醒

低概率发生调用pthread_cond_wait的线程没有被唤醒 背景: 你是否也踩过坑,在A线程调用pthread_cond_wait等待,在B线程调用pthread_cond_signal唤醒A线程进行工作处理,然后在某一次用户产品反馈中发现了低概率问题。A线程像是卡住…

Python Cookbook-2.3 搜索和替换文件中的文本

任务 需要将文件中的某个字符串改变成另一个。 解决方案 字符串对象的 replace 方法提供了字符串替换的最简单的办法。下面的代码支持从一个特定的文件(或标准输入)读取数据,然后写人一个指定的文件(或标准输出): importos,sys nargs len(sys.argv) if not 3&l…

机器学习实战(5):决策树与随机森林——直观的分类与回归方法

第5集:决策树与随机森林——直观的分类与回归方法 在机器学习中,决策树(Decision Tree) 和 随机森林(Random Forest) 是两种直观且强大的算法,广泛应用于分类和回归任务。决策树通过一系列规则…

网站中内嵌腾讯元宝用deepseek

网站中内嵌元宝deepseek <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BING搜</title> <meta name="description" content="不用学习就G搜索高级语法,即选即用…

draw.io:开源款白板/图表绘制利器

在工作和学习中&#xff0c;我们常常需要绘制各种图表&#xff0c;例如流程图、思维导图、网络拓扑图等等。一款功能强大且易于上手的图表绘制工具可以极大地提高我们的效率。今天&#xff0c;我要向大家推荐一款开源免费的图表绘制工具—— draw.io&#xff0c;并手把手教你如…

ES6箭头函数:从基础到进阶指南

目录 引言&#xff1a;新时代的函数表达 一、基础篇&#xff1a;语法与特性 1. 语法演进 2. 参数处理 3. 函数体形式 二、进阶特性深度解析 1. this绑定机制&#xff08;词法作用域&#xff09; 2. 不可构造特性 3. 与普通函数对比 三、实战应用场景 1. 数组高阶函数…

XML Schema 元素替换

XML Schema 元素替换 引言 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言。XML Schema 是一种用于定义 XML 文档结构的语言,它描述了 XML 文档的结构、数据类型和约束。在处理 XML 文档时,有时需要对特定的元素进行替换,以满足特定的需求。本文将介绍 XML Sch…

推理模型时代:大语言模型如何从对话走向深度思考?

一、对话模型和推理模型的区别概述 对话模型是专门用于问答交互的语言模型,符合人类的聊天方式,返回的内容可能仅仅只是一个简短的答案,一般模型名称后面会带有「chat」字样。 推理模型是比较新的产物,没有明确的定义,一般是指输出过程中带有<think>和</think&…

数据仓库与数据湖的协同工作:智慧数据管理的双引擎

数据仓库与数据湖的协同工作:智慧数据管理的双引擎 引言 在数据驱动的今天,企业和组织收集和存储的数据量正以惊人的速度增长。如何高效管理和利用这些数据,成为了决策者和技术专家的共同难题。为了解决这一问题,数据仓库(Data Warehouse)和数据湖(Data Lake)这两种技…

基于eBPF的全栈可观测性系统:重新定义云原生环境诊断范式

引言&#xff1a;突破传统APM的性能桎梏 某头部电商平台采用eBPF重构可观测体系后&#xff0c;生产环境指标采集性能提升327倍&#xff1a;百万QPS场景下传统代理模式CPU占用达63%&#xff0c;而eBPF直采方案仅消耗0.9%内核资源。核心业务的全链路追踪时延从900μs降至18μs&a…

【CS285】高斯策略对数概率公式的学习笔记

公式介绍 在【CS285】中提到了高斯策略对数概率公式的公式如下&#xff1a; log ⁡ π θ ( a t ∣ s t ) − 1 2 ∥ f ( s t ) − a t ∥ Σ 2 const \log \pi_{\theta}(\mathbf{a}_t | \mathbf{s}_t) -\frac{1}{2} \left\| f(\mathbf{s}_t) - \mathbf{a}_t \right\|_{\S…

图解MySQL【日志】——Binlog

Binlog&#xff08;Binary Log&#xff0c;归档日志&#xff09; 为什么需要 Binlog&#xff1f; Binlog 是 MySQL 中的二进制日志&#xff0c;用于记录数据库的所有写操作&#xff08;INSERT、UPDATE、DELETE 等&#xff09; 1. 主从复制 作用&#xff1a;是 MySQL 主从复…

Java 使用websocket

添加依赖 <!-- WebSocket 支持 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>添加配置类 Configuration public class WebSocketConfig {B…

进程的介绍--进程状态/切换

1.冯 • 诺依曼体系结构 1.1 体系结构 冯•诺依曼结构也称普林斯顿结构&#xff0c;是一种将程序指令存储器和数据存储器合并在一起的存储器结构。数学家冯•诺依曼提出了计算机制造的三个基本原则&#xff0c;即采用二进制逻辑、程序存储执行以及计算机由五个部分组成&#x…

百万架构师第三十七课:RabbitMq:高可用集群搭建步骤|JavaGuide

安装环境 Centos-7 三台虚拟机 192.168.8.150&#xff08;磁盘节点&#xff09; 192.168.8.45 &#xff08;内存节点&#xff09; 192.168.8.40 &#xff08;内存节点&#xff09;一、安装Erlang 1、erlang 下载地址&#xff1a; http://www.rabbitmq.com/releases/erlang…