最近搞的自用小工具有部署的需求,并且我很少做上线应用的工作,因此在博客记录一下这次部署,方便后续参考
项目构成:vite react 前端 + express 后端 + mongodb
第一次部署时尝试了 vercel + railway + mongodb atlas,前端部署没什么问题,后端我是第一次部署,没啥经验,一直 502,查了一下后台 console 还发现数据库访问超时了,问了一下后端的朋友说可能是因为 railway 在美国机房,我选的数据库机房地区在香港所以容易超时……但我重新注册了一个在美国的数据库之后依然超时。
鉴于本来我就不喜欢应用只能挂梯子访问这一点,所以打算前后端都用阿里云重新部署一遍,数据库则仍然白嫖 mongo 的 cluster0。
以下记录将约定我的前端部署在域名 x.psyqlk.space
,后端部署在域名 api.x.psyqlk.space
;前端使用阿里云 OSS 部署,并使用 history 方式管理路由。而后端会运行在阿里云 ECS 服务器的 3000 端口,并使用 nginx 反代到指定域名上
前端部署(OSS)
之前的博客其实有记录过前端如何用阿里云 oss 实现自动部署,但最近重新参考这篇博客部署前端的时候发现阿里云改版了不少,所以还是按照现在的排版重新记录一下吧创建 Bucket
打开 阿里云 OSS 管理控制台,点击 创建 Bucket
,其中最重要的是选择 自定义创建
并取消开通 阻止公共访问
, 读写权限
选择 公共读
,最后点击 完成创建
点击刚刚创建的 Bucket,进入 数据管理->静态页面
,将页面设置改成如下的样子(因为项目前端使用 history 路由,如果文件 404 规则没有设置为 redirect,在子路由刷新页面时会 404,很影响用户体验
进入 Bucket 配置->域名管理
,点击 绑定域名
输入你想部署到的子域名地址,如此处是 x.psyqlk.space
然后进入 Bucket 配置->传输加速
,点击 开启传输加速
,复制出现的 传输加速访问域名
的值
再进入 权限控制->Bucket 授权策略
,点击 新增授权
并确定
DNS 解析
打开阿里云云解析 DNS 控制台,在域名解析中点开当前要部署的域名,点击 添加记录
在 记录类型
中选择 cname
,主机记录
中填写想设置的二级域名的路径(此处为 x
),记录值
中粘贴刚刚复制的 传输加速访问域名
的值,点击 确认
AccessKey
创建 ACK
打开 阿里云 AccessKey 管理控制台,点击 创建用户
,勾选 OpenAPI 调用访问
开启 ACK 权限
返回 阿里云 AccessKey 管理控制台,点击列表中刚刚创建的用户的 添加选项
,搜索 AliyunOSSFullAccess
并勾选,最后点击 确认新增授权
将 AccessKey 添加到 Github Secrets
打开博客所在仓库,点击 Settings
-> Secrets
-> Actions
-> New repository secret
,创建 KEY
和 SECRET
,分别填入刚刚创建的用户的 AccessKey ID
和 AccessKey Secret
;打开 阿里云 OSS 管理控制台,点击项目对应的 Bucket,进入 概览
,翻到 访问端口
,将此处 Endpoint
的值复制到 New repository secret
并命名为 OSS_ENDPOINT
,同样将此处 Bucket 域名
的值命名为 OSS_BUCKET
然后点击博客仓库的 Actions
-> set up a workflow yourself
,为仓库添加一个 workflow。以下是 gpt 帮我生成的用于部署 vite react 项目的可用 workflow,可供参考:
name: Deploy to Aliyun OSS
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Install ossutil
run: |
wget http://gosspublic.alicdn.com/ossutil/1.7.2/ossutil64
chmod +x ossutil64
mv ossutil64 /usr/local/bin/ossutil
- name: Configure ossutil
env:
OSS_ENDPOINT: ${{ secrets.OSS_ENDPOINT }}
ACCESS_KEY_ID: ${{ secrets.KEY }}
ACCESS_KEY_SECRET: ${{ secrets.SECRET }}
run: |
ossutil config -e $OSS_ENDPOINT -i $ACCESS_KEY_ID -k $ACCESS_KEY_SECRET --language EN
- name: Clean up old files
run: |
ossutil rm oss://${{ secrets.OSS_BUCKET }}/ --recursive --force
- name: Upload to OSS
run: |
ossutil cp -r dist/ oss://${{ secrets.OSS_BUCKET }} --recursive
完成后点击 Start commit
,然后等 CICD 结果。如果显示部署成功,此时应该可以通过 x.psyqlk.space
访问部署好的前端了。
SSL 配置
由于阿里云不会泛域名解析,所以每次创建二级域名都要重复一遍这个过程
进入数字证书管理服务,选择 SSL 证书管理
-> 个人测试证书
-> 创建证书
其中,域名填写 x.psyqlk.space
,并勾选 快捷签发
。点击确认后等待签发成功,一般需要等待一两分钟。
进入对象存储 OSS 控制台,选择服务对应的 Bucket,并搜索 域名管理
,点击 证书托管
选择自己刚刚在数字服务管理平台为前端域名签发的证书。如果没有可选证书,则返回数字证书管理服务确认自己申请的证书地址
后端部署(ECS 服务器)
此处 ECS 服务器的操作系统为 CentOS
环境初始化
登录 ECS 服务器,安装 nodejs 和 nginx
sudo yum update
sudo yum install -y nodejs npm
sudo yum install nginx
拉取 private 仓库的准备(如果是 public 仓库则跳过这一步)
生成 SSH 密钥对
此处 your_email@example.com
为你在 github 的公开邮箱。若你将 github 邮箱设为私密,则使用 github 为你生成的替代邮箱,形如 73028291+psyq55262227@users.noreply.github.com
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
添加 SSH 公钥到 GitHub 仓库
复制生成的公钥内容:
cat ~/.ssh/id_rsa.pub
登录到 GitHub,进入你的私密仓库的设置页面。
导航到 Deploy keys
部分,添加一个新的 Deploy key
(命名随意,可辨认就行),并粘贴公钥内容。选择 Allow write access
选项。
将私钥添加到 ECS 实例
在 ECS 实例上创建.ssh 目录,并将私钥添加到 authorized_keys
中:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "YOUR_PRIVATE_KEY_CONTENT" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
配置 SSH Agent
确保 SSH Agent 正在运行,并添加私钥:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
拉取仓库
git clone https://github.com/your-username/your-repository.git
cd your-repository
npm install
在 express 应用配置文件更新 MongoDB 连接 URI,形如 MONGODB_URI=mongodb+srv://username:password@cluster0.mongodb.net/mydatabase?retryWrites=true&w=majority
然后用 PM2 进行进程管理
npm install -g pm2
pm2 start your-app.js
pm2 startup
pm2 save
开启安全组
进入 阿里云 ECS 控制台,点击实例并查看其安全组,然后添加 443
、80
和 3000
(后端运行端口) 端口,授权对象设置为 0.0.0.0
此时理论上可以在 {公网ip}:{后端运行端口}
访问到自己的后端
配置域名
打开阿里云云解析 DNS 控制台,在域名解析中点开当前要部署的域名,点击 添加记录
。此处选择 A 记录
,主机记录
填二级域名,记录值
填服务器公网 ip 地址
此时访问 api.x.psyqlk.space:3000
已经可以访问到后端
SSL 证书
申请 SSL 证书
打开阿里云数字证书管理服务,选择 SSL 证书管理
-> 个人测试证书
-> 创建证书
,填写完域名名称后勾选快捷签发并确定
证书签发成功后,点击 下载
并选择 nginx 的下载按钮,得到 SSL 证书的 key(ssl_certificate_key) 和 pem(ssl_certificate)
将 SSL 证书上传到服务器 & nginx 反代配置
win 可以下载 WinSCP
,将刚刚下载好的 SSL 证书上传到服务器,存放到 etc/nginx/ssl
路径
然后在 etc/nginx/conf.d
新建 nginx1.conf
和 nginx.conf
# etc/nginx/conf.d/nginx1.conf 将 http 转为 https
server {
listen 80;
server_name api.x.psyqlk.space;
rewrite /(.*) https://api.x.psyqlk.space/$1 permanent;
}
# etc/nginx/conf.d/nginx.conf 配置域名,反代服务
server {
listen 443 ssl;
# 后端部署的域名
server_name api.x.psyqlk.space;
# SSL 证书在服务器中的路径
ssl_certificate /etc/nginx/ssl/api.x.psyqlk.space.pem;
ssl_certificate_key /etc/nginx/ssl/api.x.psyqlk.space.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
add_header Content-Security-Policy upgrade-insecure-requests;
access_log /var/log/nginx/web.https.access.log;
location / {
# 后端反代的端口
proxy_pass http://localhost:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
}
启动 nginx 时,使用命令 cd /etc/nginx
& ./nginx -c /etc/nginx/nginx.conf
此时理论上 nginx 已经启动,并会将访问 api.x.psyqlk.space
的请求自动代理给后端所在的 {公网ip}:{后端端口}
服务是一周前上线的,本文属于复盘回忆产物,如有缺漏之处或有问题的地方敬请勘误