个人项目从开发到部署(CI/CD)的思路

偏向技术
/ 0 评论 / 123 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年03月25日,已超过607天没有更新,若内容或图片失效,请留言反馈。

ci-cd

在项目开发过程中,最简单的流程是开发完成后手动上传到服务器目录,再执行相关命令启动服务,这样就完成了一次上线,但随着项目不断的迭代,这样的流程就显得很繁琐,即使是前后端分离项目,每次打包根据项目的大小都需要等待一段时间,显得很机械,即使 IDE 有集成发布和部署工具,也还是需要很多步骤,当你切换 IDE 之后,原来的发布和部署工具就没有办法使用,有一定的更换成本。所以,一套自动化的发布和部署流程在项目开发过程中是必不可少的。

项目架构

前端

选用基于 Vue3 的框架和依赖

后端

BaaS(后端即服务,Backend as a Service),可以帮助我们快速构建和运行应用,通常包含身份验证、数据库、存储、网关、Web托管等服务,目前市面上最流行的是谷歌的 Firebase,但由于 GFW 原因,在国内无法使用 Firebase 的服务,这里我们选用开源的 Supabase,用以替代 Firebase,Supabase 包含免费套餐和专业套餐,基于成本考虑,这里选择暂时使用 Supabase 的免费套餐,Supabase 也提供自建服务,允许你通过 Docker 部署私有的 Supabase 服务。仓库地址

Docker Compose

管理多个 docker 应用,将前端项目容器化,方便集成其他项目,比如添加 Supabase 后端服务,添加 Python 爬虫服务。同时只要服务器安装了 Docker 和 Docker Compose,就免掉了安装其他环境的时间。

Lerna

Lerna 是一个多包管理工具(monorepo),用于管理包含多个软件包(package)的 JavaScript 项目。虽然开发项目不属于package,但只要将 packages 目录下面的前端项目的 package.json 设置为 private,当执行 lerna publish 的时候就不会发布到 npm 上。不论是开发 App 还是 Library,不论是个人项目还是企业项目,我们都可以利用 Lerna 来进行管理。仓库地址

CI/CD

当项目初始版本开发完成后,接着需要考虑如何部署到线上,以减少开发和部署之间的流程,尤其是需要频繁发布的项目。普遍来说,项目正式上线有确立需求、开发、构建、测试、部署等一些个流程,CI/CD 正是一套在构建、测试、部署流程中实施自动化的组合实践。

常见的 CI/CD 工具有 GitLab CI、Travis CI、Jenkins、Github Action、TeamCity、腾讯云Coding、阿里云云效等,考虑到本地开发机性能问题,选择第三方的构建服务器,每月提供一定的免费构建时长,GitLab 是400分钟,由于有人挖矿,需要提供信用卡信息;Github 是2000分钟;Travis CI 一次性赠送10000 积分,这个积分不会刷新,用完就没了;TeamCity 托管需要许可证;腾讯云Coding 是1000分钟,并发任务数是1,单次构建上限30分钟;阿里云云效是1800分钟,并发任务数是3。使用Windows 和 Mac OS 时分钟数换算有一定比例,这里根据代码托管在 Github 私有存储库和构建时长,选择 Github Action。

Github Action 里的主要步骤是:检出代码 - 安装依赖打包 - 推送到服务器 - 执行相关命令,社区已经有不少的插件足够我们直接使用。编写工作流程中使用到的环境变量是通过在 Github 上的 Settings - Secrets - New repository secret 中添加 key - value 键值对来保证变量不会泄露,使用方式是在 .github/workflows/*.yml 文件中以 secrets.KEY 的格式引用。GitHub Action 执行失败的时候,会以邮件的形式通知到用户。

  • actions/checkout@v2:检出代码插件

  • actions/setup-node@v2:Node 环境插件

  • easingthemes/ssh-deploy@main:SSH 部署插件,用到的环境变量

    • SSH_PRIVATE_KEY:SSH 私钥
    • SOURCE:源目录,Github Action 工作流程中的目录
    • REMOTE_HOST:远程服务器地址
    • REMOTE_USER:远程登录用户名
    • TARGET:目标目录,远程服务器上的目录
  • appleboy/ssh-action@master:SSH 远程执行命令插件,用到的变量

    • host:远程服务器地址
    • username:远程登录用户名
    • key:SSH 私钥
    • port:22(没有修改的情况下)
    • script:需要在远程服务器上执行的命令

代码

基本目录

bash
.
|-- .eslintignore
|-- .eslintrc
|-- .github
|   `-- workflows
|       `-- deploy.yml
|-- .gitignore
|-- .prettierrc.toml
|-- lerna.json
|-- package.json
|-- node_modules
|-- packages
|   |-- docker
|   |   `-- docker-compose.yml
|   `-- web
|       |-- .nuxt
|       |-- .output
|       |-- Dockerfile
|       |-- README.md
|       |-- layouts
|       |-- nuxt.config.ts
|       |-- package.json
|       |-- node_modules
|       |-- pages
|       `-- tsconfig.json
|-- readme.md
`-- yarn.lock
123456789101112131415161718192021222324252627

在前端项目下,添加 Dockerfile 文件,这里选用的是 node:lts-alpine3.14 镜像

Dockerfile
FROM node:lts-alpine3.14

WORKDIR /app
COPY ./.output ./.output
COPY ./package.json ./package.json

EXPOSE 3000
CMD ["npm", "start"]
12345678

在 docker 项目下,添加 docker-compose.yml

bash
version: "3"

services:
  web:
    build: ../web
    restart: always
    ports:
      - "3000:3000"
    environment:
      HOST: 0.0.0.0
12345678910

如果还有其他服务,统一放在 packages 目录下

.github/workflows 目录下面添加 ci.yml 文件

yaml
name: Deploy CI

# 触发工作流程的事件,只有 push 到 master 分支的才会执行下面的任务
on:
  push:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest
    # 判断 job 是否执行,当提交的消息中包含 'chore(release): publish' 时才会执行 build
    if: contains(github.event.head_commit.message, 'chore(release): publish')
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '14.x'
          cache: 'yarn'

      - name: Install dependencies
        run: yarn --immutable

      - name: Build web
        run: yarn build

      - name: Generate deploy folder and move files
        run: |
          mkdir -p deploy/web
          mv packages/web/.output packages/web/package.json packages/web/Dockerfile -t deploy/web
          mv packages/docker -t deploy

      - name: Deploy to Staging server
        uses: easingthemes/ssh-deploy@main
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
          ARGS: "-rltgoDzvO --delete"
          SOURCE: "deploy/"
          REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
          REMOTE_USER: ${{ secrets.REMOTE_USER }}
          TARGET: ${{ secrets.REMOTE_TARGET }}

      - name: Setup docker compose
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: ${{ secrets.REMOTE_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          port: 22
          script: |
            cd ${{ secrets.REMOTE_TARGET }}/docker
            docker-compose up -d --build --force-recreate
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950

总结

有一套属于自己可重复使用的自动化部署流程,能够大幅度节省其中的时间,能够更加专注开发,即使是一个简单的项目,也建议通过 CI/CD 的方式来进行发布部署,虽然每个项目情况不一样,但部署流程总体差不太多。

将每个项目视为一个 package,利用 Lerna 管理 packages,将每个项目容器化,作为 Docker Compose 中的一个应用,统一进行管理,减少迁移和维护成本,通过 Github Action 实现 CI/CD 流程,进行测试、构建、部署,可以实现多环境、多版本上线。

参考来源

[1]: 什么是 CI/CD?
[2]: 谁才是世界上最好的 CI/CD 工具?

0

评论 (0)

取消