Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

介绍

项目部署的方式很多,针对不同的项目也有不一样方式,下面说一下常见的项目部署是怎么样的。

首先呢你需要有一个云服务器 💰。

基本配置

以 node.js 的 express 为例,

1
2
3
4
const express = require("express");
const app = express();
// 静态资源路径
app.use(express.static(path.join(__dirname, "dist")));

然后将打包好的 dist 文件的内容放到 dist 目录下,此时前端代码的 BASE_URL 可以为空,这样会自动带上当前的路径直接请求后端接口。然后使用pm2启动后端的 node 服务pm2 start app.js --name expo,然后使用 nginx 将域名和端口关联起来即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
listen 443;
ssl on;
#配置HTTPS的默认访问端口为443。
#如果未在此处配置HTTPS的默认访问端口,可能会造成Nginx无法启动。
#如果您使用Nginx 1.15.0及以上版本,请使用listen 443 ssl代替listen 443和ssl on。
server_name expo.liufashi.top; #需要将yourdomain替换成证书绑定的域名。

ssl_certificate ssl/expo/expo.liufashi.top.pem; #需要将cert-file-name.pem替换成已上传的证书文件的名称。
ssl_certificate_key ssl/expo/expo.liufashi.top.key; #需要将cert-file-name.key替换成已上传的证书私钥文件的名称。
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#表示使用的加密套件的类型。
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; #表示使用的TLS协议的类型。
ssl_prefer_server_ciphers on;
location / {
root /root/app/dist;
index index.html;
proxy_pass http://localhost:3000;
}
}
server {
listen 80;
server_name expo.liufashi.top; #需要将yourdomain替换成证书绑定的域名。
rewrite ^(.*)$ https://$host$1;
}

查看项目。这样做的好处是只需要启动一个后端服务。然后使用<公网 ip>:<端口>就可以访问了。但是当前端应用和后端服务不使用同一个域名的时候这个方法就不实用了。这个时候还需要将不同的域名代理到对应前端应用的静态资源,然后前端的 BASE_URL 需要时后端的域名。例如上面的应用还有个移动端
pc 端配置

1
2
3
4
5
6
7
8
9
10
11
server {
listen 443;
ssl on;
server_name expo.liufashi.top;
...
location / {
root /apps/expo-pc/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}

移动端配置

1
2
3
4
5
6
7
8
9
10
11
server {
listen 443;
ssl on;
server_name mobile.expo.liufashi.top;
...
location / {
root /apps/expo-mobile/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}

项目部署

简单的来说将项目从电脑里复制到云服务器上,云服务器可以理解为另一台电脑,只不过是 linux(也可以购买其他系统),需要使用命令行工具操作,或者使用其他可视化工具,亦或是给你的 linux 系统安装桌面 GNOME、Pantheon 等等(服务器配置有限,亲测很卡)。

刀耕火种

使用 scp 命令将项目从本地复制到云服务器scp -r <本地路径> <user>@公网ip>:<服务器目标路径>,然后使用密码连接,如果配置了 ssh 免密就可以直接复制过去了。

然后还有一些方法,例如在服务器上配置 git,拉取代码->安装依赖->打包->移动打包产物。
以上这些方法过于麻烦,如果是自己的服务器比较熟悉,可以自己想怎么玩怎么玩,如果是在公司的话实现可能每次更新内容需要联系运维的同学。这个时候就需要一个自动化的工具了,一次配置,后面都能自动化部署。

git action 实现自动化部署

可以参考GitHub Actions 入门教程

GitHub 有一个官方市场,可以搜索到他人提交的 actions。另外,还有一个 awesome actions 的仓库,也可以找到不少 action。如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。

GitHub Actions 有一些自己的术语。

  1. workflow (工作流程):持续集成一次运行的过程,就是一个 workflow。

  2. job (任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。

  3. step(步骤):每个 job 由多个 step 构成,一步步完成。

    • name:该步骤的名字,在命令行能够看到,
    • uses:需要安装的第三方包
    • with:包需要的一些参数
  4. action (动作):每个 step 可以依次执行一个或多个命令(action)。

知道了这些我们就可以自己实现一个简易的自动化部署流程

首先在项目根目录新建.github/workflows 文件夹,仓库中的 action 会检测到该文件加下的 yml 文件,新建一个 yml 文件随便取名,我这里叫 deploy.yml,添加如下代码,代码中有注释会告诉你每一行的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 指定工作流程的名称
name: CI/CD
# 指定此工作流程的触发事件Event。 此示例使用 推送 事件,即执行push后,触发该流水线的执行
on: [push]
# 存放 learn-github-actions 工作流程中的所有Job
jobs:
# 指定一个Job的名称为check-bats-version
deploy:
runs-on: ubuntu-latest
steps:
# 拉取项目代码
- name: Checkout repository
uses: actions/checkout@v3
# 给当前环境下载node
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "14.x"
- name: use yarn.js 1.22.19
# 使用action库 actions/setup-node安装yarn
uses: actions/setup-node@v3
with:
yarn-version: 1.22.19
# 检查缓存
# 如果key命中缓存则直接将缓存的文件还原到 path 目录,从而减少流水线运行时间
# 若 key 没命中缓存时,在当前Job成功完成时将自动创建一个新缓存
- name: Cache
# 缓存命中结果会存储在steps.[id].outputs.cache-hit里,该变量在继后的step中可读
id: cache-dependencies
uses: actions/cache@v3
with:
# 缓存文件目录的路径
path: |
**/node_modules
# key中定义缓存标志位的生成方式。runner.OS指当前环境的系统。外加对yarn.lock内容生成哈希码作为key值,如果yarn.lock改变则代表依赖有变化。
# 这里用yarn.lock而不是package.json是因为package.json中还有version和description之类的描述项目但和依赖无关的属性
key: ${{runner.OS}}-${{hashFiles('**/yarn.lock')}}
# 安装依赖
- name: 安装依赖
# 如果缓存标志位没命中,则执行该step。否则就跳过该step
if: steps.cache-dependencies.outputs.cache-hit != 'true'
run: yarn
# 运行代码打包
- name: node.js构建
run: CI=false yarn run build
- name: 查看文件
run: ls -a # 查看打包后的目录文件
- name: oss上传
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }} # 服务器host
username: ${{ secrets.USER }} # 服务器用户名
password: ${{ secrets.PASSWORD }} # 服务器密码
source: "./build" # 需要上传的文件, 多文件使用逗号隔开
target: "/apps/react-admin/" # 上传到服务器的什么位置

上述涉及到私密信息的我们会在仓库中配置,然后是采用${{ secrets. }}可以拿到

当然以上只是提供了最简单的自动化部署的方式,最后打包产物上传采用的是appleboy/scp-action@master这个包。还有类似的如easingthemes/ssh-deploy@v2.1.1等等

使用 jenkins 实现自动化部署

CI/CD

先来说下什么是 CI,持续集成(Continuous Integration)的缩写。指的一个流程,即当有新的需求时

  1. 从最新的 master 分支切出一个 feature 分支进行开发
  2. 开发过程中将更改提交到 feature 分支
  3. 将 feature 的代码部署至测试环境,进行测试
  4. 通过测试后将 feature 分支的代码通过 pull_request 合并到 master

而 CD 通常解释为两个步骤持续交付(Continuous Delivery)和持续部署(Continuous Deployment),持续交付指的是,频繁地将软件的新版本,交付给质量团队,以供评审。如果评审通过,代码就进入生产阶段,也就是持续部署

以上是我结合公司业务对 CI/CD 的理解,不同情况下可能会有些许出入。

评论

填写正确的邮箱更便于接收消息!



本站总访问量为 访客数为