在项目开发过程中,最简单的流程是开发完成后手动上传到服务器目录,再执行相关命令启动服务,这样就完成了一次上线,但随着项目不断的迭代,这样的流程就显得很繁琐,即使是前后端分离项目,每次打包根据项目的大小都需要等待一段时间,显得很机械,即使 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:需要在远程服务器上执行的命令
代码
基本目录
.
|-- .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
在前端项目下,添加 Dockerfile 文件,这里选用的是 node:lts-alpine3.14 镜像
FROM node:lts-alpine3.14
WORKDIR /app
COPY ./.output ./.output
COPY ./package.json ./package.json
EXPOSE 3000
CMD ["npm", "start"]
在 docker 项目下,添加 docker-compose.yml
version: "3"
services:
web:
build: ../web
restart: always
ports:
- "3000:3000"
environment:
HOST: 0.0.0.0
如果还有其他服务,统一放在 packages 目录下
在 .github/workflows
目录下面添加 ci.yml 文件
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
总结
有一套属于自己可重复使用的自动化部署流程,能够大幅度节省其中的时间,能够更加专注开发,即使是一个简单的项目,也建议通过 CI/CD 的方式来进行发布部署,虽然每个项目情况不一样,但部署流程总体差不太多。
将每个项目视为一个 package,利用 Lerna 管理 packages,将每个项目容器化,作为 Docker Compose 中的一个应用,统一进行管理,减少迁移和维护成本,通过 Github Action 实现 CI/CD 流程,进行测试、构建、部署,可以实现多环境、多版本上线。
参考来源
[1]: 什么是 CI/CD?
[2]: 谁才是世界上最好的 CI/CD 工具?
评论 (0)