Open vortesnail opened 1 year ago
当你想把开发的前端项目和 Node 服务端项目部署至云服务器上,以便于别人能够公网访问,相信大多数开发者都要经历一个查来查去的过程,还容易踩坑。这篇文章会一步一步地教你如何做,可以让你少走些弯路。 在开始之前,我先介绍下我的项目技术栈:
很常规,其实这篇教程和技术栈是没有任何关系的,毕竟我们要部署的前端项目只是打包后的静态资源文件而已,服务端进程管理器目前最好的选择也就 pm2 。
现在的云服务器选择很多,比如腾讯云、阿里云等其它云,这里讲下阿里云服务器 ECS 的购买,后续的服务器配置等操作都是基于我们购买的云服务器进行的,所以如果你购买的不是阿里云的,可能本教程只能作为一个参考。
访问 阿里云服务器 ECS 主页 往下翻到产品规格,有许多种类型的服务器供我们选择,我是购买了共享型下的 2 核 4G 实例,即下图:
你看到的价格可能不一样,会因为活动(比如双 11、618)、新客专享和学生优惠,有更低的价格,总之看你用途是什么吧,个人的学习项目或博客啥的,买便宜点的就行了。 购买配置如下:
有了服务器之后自然是要登录上去进行操作,下面介绍密码登录和本地远程面密登录。
我们先尝试下通过 Workbench 远程连接服务器,如下图操作:
在这里你可能会遇到无法使用密码登录的问题,首先你要保重重置了实例密码,然后通过 VNC 远程连接,创建 6 位的密码后,进入页面登录实例:
Login: root Password: 输入你创建的实例密码,不是 VNC 密码
然后按照这个文档 使用密码无法登录 Linux 云服务器 ECS 该如何处理?操作就行了。
重启退出后我们再点远程连接,就可以正常通过密码登录了,然后就可以操作我们的服务器咯。
如果我们想在自己电脑上就快捷登录到云服务器系统上,可以打开终端,因为我是 Windows 系统,所以使用的是 PowerShell ,然后输入以下命令:
ssh root@111.11.1.1
上面 root 是登录用户名,后面的 111.11.1.1 是服务器实例的公网 IP,记得替换成你自己的公网 IP。回车之后会让你输入登录密码,即服务器实例密码。
root
111.11.1.1
但是我们每次打开终端都要执行一遍登录,还要输入密码,特别麻烦,而且不利于后面要讲到的利用 Github Actions 自动化部署的工作进行。
幸运的是可以让本机与云服务器建立信任,实现免密登录,接下来介绍实现建立信任步骤:
在本机的终端输入以下命令:
ssh-keygen -t rsa -C "你的 github 邮箱"
执行上面命令以后,要找到 id_rsa.pub 文件,我的电脑上路径是 C:\Users\10913\.ssh ,你可以做个参考,然后随便找个编辑器将其打开后,复制该文件内的所有内容,复制到云服务器上的 ~/.ssh/authorized_keys 文件中(如没有该文件,就创建一个)。
id_rsa.pub
C:\Users\10913\.ssh
~/.ssh/authorized_keys
上述过程用到步骤命令如下:
# 登录云服务器 ssh root@47.97.100.103 # 来到 ~/.ssh 目录 cd ~/.ssh # 查看下有没有 authorized_keys 文件 ls # 没有的话创建一个 touch authorized_keys # 编辑该文件 vi authorized_keys # 粘贴后退出,先按 ESC,然后 :wq
然后你输入 exit 命令退出云服务器系统,再重新执行上述登录,就不用输入密码了。
exit
如果还是需要你输入密码,估计是权限不够,我们使用密码再次登录后,依次执行以下命令:
cd .ssh chmod 700 ../ chmod 700 . chmod 600 authorized_keys
云服务器的初始系统是比较干净的,有些必要的软件需要我们自己安装。比如,开发的服务端没有 Node 怎么那可不行。
在开始安装之前,要确认我们的云服务器能访问外网,简单的方法就是 ping 一下随便一个域名,比如:
ping
ping www.baidu.com
如果是像下面一样,就代表网是通的。
因为我购买云服务器时选择的系统是 CentOS,自带 yum ,所以我可以使用它来安装 git :
sudo yum install git
安装完成之后,查看 git 版本:
git --version
继续使用 yum 安装:
sudo yum install nginx
安装完成之后,查看 nginx 版本:
nginx -v
wget 可以在控台访问一个 url 地址,并得到返回结果,用于下载软件,也可用于测试 web server 是否正常运行。
sudo yum install wget
nvm 是一个 node 包版本管理工具,非常好用,使用 wget 来安装:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
下载的版本最好保持最新,可在 nvm 官方文档 随时查看。
注意,你大概率会遇到无法下载的问题,也就是连接不到资源,建议多尝试下,或者联系阿里云技术支持。
如果你安装成功了之后,需要重新连接服务器,查看 nvm 版本:
nvm -v
有了 nvm,可以很方便地安装 node 的不同版本,因为我本地开发项目时 node 版本是 16.19.0 ,所以为了保持一致,我准备在云服务器上也安装一个相同的版本。 执行以下命令以查看 node 版本有哪些:
16.19.0
nvm ls-remote
然后选一个版本开始安装:
nvm install 16.19.0
安装成功之后确认下:
nvm list
查看当前使用的 node 版本:
node -v
因为我使用的时 yarn 包管理器,需要安装下:
npm install --global yarn
查看当前使用的 yarn 版本:
yarn -v
使用 npm 直接安装 pm2 :
npm install pm2 -g
查看当前使用的 pm2 版本:
pm2 -v
必须的环境准备好之后,我们需要确认公网是否能访问我们的服务器资源,所以需要先写个测试的 demo 。
在根目录下,新建一个测试目录,进入该目录:
mkdir test-demo cd test-demo
然后在该目录下新建一个 html ,并编辑:
touch test.html vi test.html
编辑内容如下:
<h1>Hello World</h1>
执行以下命令查看 nginx.conf 的所在位置:
nginx.conf
nginx -t
直接开始编辑:
vi /etc/nginx/nginx.conf
添加一个 server :
server
server { listen 8001; server_name test-demo; root /root/test-demo; include /etc/nginx/default.d/*.conf; }
:wq 保存退出之后,再执行下 nginx -t 看是否正常。如果正常,重启下 nginx :
:wq
nginx -s reload
然后使用 wget 测试下是否能正常访问该目录下的资源:
wget http://localhost:8001/test.html
结果报了 403 的错误,表示没有相关权限,我们去修改 nginx.conf 文件,把 user nginx 改成 user root 就可以了。
user nginx
user root
我们再试一下使用 pm2 启动一个 node 服务。首先来到 test-demo 下新建一个 server.js :
test-demo
server.js
cd /root/test-demo touch server.js
编辑该 js 文件并输入以下内容:
const http = require("http"); const server = http.createServer((req, res) => { res.writeHead(200, { "Content-type": "application/json" }); res.end( JSON.stringify({ errno: 0, msg: "Hello node server!", }) ); }); server.listen(8002);
保存退出后启动 node 服务:
pm2 start server.js
使用 wget 测试服务是否启动成功:
wget http://localhost:8002
执行之后会默认下载一个 index.html 文件,我们查看下它的里面是什么内容:
index.html
cat index.html
如果输出了以下内容就代表我们的服务启动了:
{"errno":0,"msg":"Hello node server!"}
云服务器是有一个公网 IP 的,这意味着我们可以在公网访问其服务器资源,但是需要配置防火墙。 我们可以先尝试访问下公网 IP 获取上面创建的 test.html ,在浏览器打开以下地址(记得替换你的公网 IP):
test.html
http://111.111.11.1:8001/test.html
或者上面创建的 node 服务:
http://111.111.11.1:8002
不出意外的话,是完全不可访问的。需要回到阿里云平台配置安全组开放我们的端口,如下图:
现在再访问应该就可以了。
每次发布新的代码都要登录到服务器,手动部署最新的代码,这是重复且容易犯错的一个过程,如果我们能让机器自己执行这个过程,大大降低了风险和解放了劳动力。
Github Actions 是 Github 免费提供的一个持续集成服务,接下来介绍如何做。
之前我们说过本机与远程的云服务器建立了信任得以免密登录,现在我们使用 Github Actions 提供的临时的虚拟机也就相当于我们的本机,也要建立信任,才能方便进行后续文件拷贝的工作。
还记得之前已经我们的公钥(即 id_rsa.pub)添加到云服务器,如果我们把本机的私钥(即 id_rsa)搬到虚拟机上,不就可以模拟本机免密登录了吗!
id_rsa
来到我们的 github 项目下,找到以下新建 secret 的地方,新建一个私钥的 secret :
secret
切记,私钥一定不能泄露,不然别人能随便就登进你的服务器了。
成功之后如下图,另外我还建了其它的 secret ,服务器的公网 IP 和项目目录地址。
现在我先部署我的 type-room-web 前端项目。
type-room-web
在项目的根目录下新建 .github 目录,再新建 workflows 目录,最后在新建 deploy.yml 文件,编辑这个文件:
.github
workflows
deploy.yml
name: deploy type-room-web on: push: branches: - "main" # 针对 main 分支 paths: - ".github/workflows/*" - "src/**" - "public/*" - "package.json" - "vite.config.ts" - "index.html" jobs: deploy: runs-on: ubuntu-latest steps: - name: 拉取项目代码 uses: actions/checkout@v3 - name: 设置 node 环境 uses: actions/setup-node@v3 with: node-version: "16.19.0" - name: 安装依赖 run: yarn - name: 编译打包 run: yarn build - name: 设置 id_rsa run: | mkdir -p ~/.ssh/ echo "${{secrets.VORTESNAIL_ID_RSA}}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan ${{secrets.REMOTE_HOST}} >> ~/.ssh/known_hosts cat ~/.ssh/known_hosts - name: 将远程服务器的对应目录下所有文件及文件夹删除 run: | # type-room/web ssh root@${{secrets.REMOTE_HOST}} " cd /root/${{secrets.REMOTE_WEB_DIR}}; rm -rf ./*; " - name: 将编译后的包复制到远程服务器对应目录 run: scp -r ./dist root@${{secrets.REMOTE_HOST}}:/root/${{secrets.REMOTE_WEB_DIR}} - name: 删除 id_rsa run: rm -rf ~/.ssh/id_rsa
总结下上面文件做的事情:
main
src/**
secrets
.ssh/id_rsa
.ssh/known_hosts
dist
⚠️ 这里请务必注意,你要事先在云服务器上建好你要操作的目录,比如我的 /root/type-room/web 。 万事俱备,现在让我们提交一波前端的项目看看:
/root/type-room/web
git add -A git commit -m "ci: 测试 GitHub Actions 持续集成" git push origin main
因为现在用到的是我们实际的项目,所以需要修改之前的 nginx 配置文件:
# gzip 配置 gzip on; gzip_static on; gzip_min_length 5k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 7; gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; gzip_vary on; server { listen 8088; server_name type-room-web; root /root/type-room/web/dist; include /etc/nginx/default.d/*.conf; # 单页应用 try file location / { try_files $uri $uri/ /index.html; } # api 重定向到我们自己的服务端地址 location /api/ { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://localhost:7077; } }
如果顺利的话,你会看到每一步都是 OK 的,如果遇到了问题,不要慌,根据错误提示去解决,放心,不难的。
我购买的是下面这个,新人专享还是蛮便宜的:
首先要来到我们购买的数据库控制台,点击实例进入后来到账号管理,创建一个主账号:
然后就可以用这个账号登录数据库了:
目前只能通过阿里云自研的 DMS 进行数据库管理,如果你想在自己常用的电脑上连接远程数据库,需要开放外网访问,且要给自己的本机 IP 加白名单。
等待一会儿后,点击外网地址旁边的设置白名单,添加一个白名单组,把你的本机出口 IP 地址添加上去:
⚠️ 也可以再新建一个安全组,专门放你的云服务器内网和外网地址,这样后续可以通过内网连接数据库。
这一步做完,就可以在本机连接我们的远程是数据库了,比如我使用 MySQL Workbench 来进行连接:
来到我们的 node 服务端项目,你必然是会有一个数据库连接地址的,将其修改为云数据库的内网地址:
// 开发配置 let MYSQL_CONF = { host: "localhost", port: "3306", user: "root", password: "xxx", database: "type_room_db", }; // 线上配置 if (isProd) { MYSQL_CONF = { host: "你的云数据库内网地址", port: "3306", user: "root", password: "xxx", database: "type_room_db", }; }
在项目根目录下新建 ecosystem.config.js 文件,写入 pm2 所需的配置:
ecosystem.config.js
module.exports = { apps: [ { name: "type-room-server", script: "./bin/www", instances: "2", watch: true, ignore_watch: ["logs", "node_modules"], error_file: "./logs/err.log", out_file: "./logs/out.log", log_date_format: "YYYY-MM-DD HH:mm:ss", }, ], };
增加 package.json 中的生产环境启动服务命令 prod :
package.json
prod
"scripts": { "dev": "cross-env NODE_ENV=dev ./node_modules/.bin/nodemon bin/www", "prod": "cross-env NODE_ENV=production pm2 start ecosystem.config.js", },
和前端项目一样,也要创建我们的 .github/workflows/deploy.yml ,写入以下内容:
.github/workflows/deploy.yml
name: deploy type-room-server on: push: branches: - "main" # 针对 main 分支 paths: - ".github/workflows/*" - "src/**" - "bin/*" - "package.json" - "ecosystem.config.js" - ".env" jobs: deploy: runs-on: ubuntu-latest steps: - name: 拉取项目代码 uses: actions/checkout@v3 with: path: "clone-files" - name: 设置 id_rsa run: | mkdir -p ~/.ssh/ echo "${{secrets.VORTESNAIL_ID_RSA}}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan ${{secrets.REMOTE_HOST}} >> ~/.ssh/known_hosts cat ~/.ssh/known_hosts - name: 将远程服务器的对应目录下所有文件及文件夹删除 run: | # type-room/server ssh root@${{secrets.REMOTE_HOST}} " cd /root/${{secrets.REMOTE_SERVER_DIR}}; pm2 kill; rm -rf ./*; " - name: 将项目复制到远程服务器对应目录 run: | rsync -avz --exclude=".git" --exclude="node_modules" clone-files/ root@${{secrets.REMOTE_HOST}}:/root/${{secrets.REMOTE_SERVER_DIR}} ls -a - name: 启动 pm2 run: | ssh root@${{secrets.REMOTE_HOST}} " cd /root/${{secrets.REMOTE_SERVER_DIR}}; ls -a; yarn; yarn prod; " - name: 删除 id_rsa run: rm -rf ~/.ssh/id_rsa
和 web 项目不一样的是,复制时使用的是 scp ,现在我们用的是 rsync ,两者区别大家可以自行查查。
scp
rsync
然后我们提交代码到 github 远程仓库,在 actions 里面看下我们的 ci 流程是否正常。
现在 node 服务是部署好了,我们可以登录云数据库,创建数据库,我的创建格式如下:
创建好数据库,我需要去创建和我开发环境保持一直的数据库表,因为我用的是 sequelize ,我在云服务器的 node 项目根目录下执行下写有同步逻辑的 js 文件就可以了。比如我的同步操作:
sequelize
./node_modules/.bin/cross-env NODE_ENV=production node ./src/db/sync.js
同步成功之后,就可以开始读写数据库了,截止目前,你的 web 和 node 项目都已经完成了线上自动化部署、公网访问的所有流程了。
现在访问我们的页面只能通过服务器的公网 IP 去访问,我们希望通过自己购买的域名去进行访问,该怎么做呢? 首先,找到域名解析,你会看到你购买的域名:
在列表的最右边有解析设置按钮,点击跳转之后,再点击新手引导,填入以下信息:
记住要把对应设置"@"主机记录和对应设置"www"主机记录都勾选上,前者可以让你不输入 www 时也能正常访问。
www
设置之后我们打开终端,测试下域名的连通性,我们 ping 一下域名:
ping www.typeroom.cn # 或 ping typeroom.cn
如果能正确显示出云服务器的 IP 地址表示成功了:
这个时候,已经可以使用域名代替之前的公网 IP 访问了,就像我的这样:
http://www.typeroom.cn:8088
细心的同学会发现,我现在访问页面还需要加端口 8088 才行,这是因为我云服务器的 nginx 配置中将前端资源的 server 端口设置成了 8088 ,将它改成 80 端口:
8088
80
server { listen 80; server_name type-room-web; root /root/type-room/web/dist; include /etc/nginx/default.d/*.conf; .... }
回到阿里云服务器实例的控制台,将安全组规则中原来的 8088 改成 80 :
改完之后再访问我们的页面,即不加端口的地址:
http://www.typeroom.cn
结果出现这个提示:
原因时我们的网站没有进行备案,那接下来就去备案呗~
访问阿里云网站备案,按照流程填写资料,提交申请后只能等待了。
如果你的居住地和户籍地不一致,要事先去办理流动人口居住证,阿里云那边审核的时候肯定会给你打电话的,所以事先准备好吧。
后续如果一切顺利的话,你的域名就可以正常访问了。
https 想必 http 的优势是什么就不说了,老生常谈了,你的网站如果不是 https,在如今,对你的访问量几乎是打击性的。
但是付费的 SSL 证书是真的贵!接下来为大家演示下如何申请免费的证书,并让你的网站支持 https 访问。这一切得益于 Let's Encrypt 免费证书 。
可以参考这个视频一起做,注意变化:https://www.bilibili.com/video/BV1Vh4y1u7ZC
Certbot 是 Let's Encrypt 推出的获取证书的客户端,可以让我们免费快速地获取 Let's Encrypt 证书。
先安装必要的软件:
yum install epel-release -y yum install certbot -y
接着生成泛域名证书(别忘了写的是你自己的域名哦):
certbot certonly --preferred-challenges dns --manual -d *.typeroom.cn --server https://acme-v02.api.letsencrypt.org/directory
执行上面命令后会连续回答几个问题,该填邮箱就填,该同意的就同意,直到出现这个提示:
回到阿里云域名解析,添加一条 TXT 的解析:
TXT
添加完解析后稍等几秒钟,即可回车继续,这时候就会校验记录是否有效。
出现这个 Congratulations 就算是成功了!!生成的证书在 /etc/letsencrypt/live 目录下。
/etc/letsencrypt/live
原来 http 访问的是 80 端口,我们需要修改为 443 端口,并增加证书的配置:
443
server { listen 443 ssl; server_name *.typeroom.cn; # 证书位置 ssl_certificate /etc/letsencrypt/live/typeroom.cn/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/typeroom.cn/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; # 静态页面目录 root /root/type-room/web/dist; include /etc/nginx/default.d/*.conf; error_page 404 /404.html; location = /404.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } location / { try_files $uri $uri/ /index.html; } location /api/ { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://localhost:7077; } } # http 访问转至 https 访问 server { listen 80; server_name *.typeroom.cn; root /usr/share/nginx/html; # 下面这行不加会导致无法重定向! include /etc/nginx/default.d/*.conf; rewrite ^(.*)$ https://${host}$1 permanent; }
修改配置之后要重启下 nginx :
systemctl restart nginx
之前云服务器的安全组配置是开放了 80 端口,现在需要新增一个 443 端口。
不出意外的话,现在你可以使用 https 访问你的网站了!但是意外总会出现,比如访问 https 还是不通。但是我们不慌,一步一步解决。
可先通过以下命令查看 nginx 进程的 pid 和监听的端口:
ps aux | grep nginx # 比如 master process 的 pid 为 9690 netstat -anp | grep 9690
发现已经监听 80 和 443 了:
我们先看下 nginx 服务的状态:
systemctl status nginx
结果报红了:
重启 nginx 也是失败:
百般不得其解,直到看到这个问题:
nginx.service failed because the control process exited
最高赞的回答解决了这个问题,首先找到当前占用了 80 和 443 端口的进程,发现就是 nginx 的:
netstat -tulpn
然后根据 pid (比如 9680)杀掉这个进程:
pid
sudo kill -2 9680
这个时候再重启 nginx 服务就可以了:
免费证书有效期 3 个月,到期之后我们可以再次续期,达到永久免费的效果。
https://www.frankfeekr.cn/2021/03/28/let-is-encrypt-cerbot-for-https/index.html https://juejin.cn/post/7205839782381928508#comment
阿里云的国内服务器,访问 github 时经常访问不到,可以尝试修改下本地的 hosts,但是 github 的访问 ip 经常变动,每次都要手动去更新 ip。
好在有 GitHub520 这个项目,让我们写个定时任务,实时拿最新的 ip 写入到系统的 hosts 配置文件中,比如 CentOS 下是 /etc/hosts 。
/etc/hosts
首先写入一个定时任务:
crontab -e
另起一行后,写入以下内容:
0 */1 * * * /usr/bin/sed -i "/# GitHub520 Host Start/Q" /etc/hosts && curl https://raw.hellogithub.com/hosts >> /etc/hosts && /usr/bin/sed -i "/<html>/, /<\/html>/d" /etc/hosts
每个 1 天就会去获取最新的数据进行写入。
:wq 保存之后重启下 crontab 服务:
crontab
systemctl restart crond.service
大功告成!
当你想把开发的前端项目和 Node 服务端项目部署至云服务器上,以便于别人能够公网访问,相信大多数开发者都要经历一个查来查去的过程,还容易踩坑。这篇文章会一步一步地教你如何做,可以让你少走些弯路。 在开始之前,我先介绍下我的项目技术栈:
很常规,其实这篇教程和技术栈是没有任何关系的,毕竟我们要部署的前端项目只是打包后的静态资源文件而已,服务端进程管理器目前最好的选择也就 pm2 。
购买云服务器
现在的云服务器选择很多,比如腾讯云、阿里云等其它云,这里讲下阿里云服务器 ECS 的购买,后续的服务器配置等操作都是基于我们购买的云服务器进行的,所以如果你购买的不是阿里云的,可能本教程只能作为一个参考。
访问 阿里云服务器 ECS 主页 往下翻到产品规格,有许多种类型的服务器供我们选择,我是购买了共享型下的 2 核 4G 实例,即下图:
你看到的价格可能不一样,会因为活动(比如双 11、618)、新客专享和学生优惠,有更低的价格,总之看你用途是什么吧,个人的学习项目或博客啥的,买便宜点的就行了。 购买配置如下:
连接服务器
有了服务器之后自然是要登录上去进行操作,下面介绍密码登录和本地远程面密登录。
密码登录服务器
我们先尝试下通过 Workbench 远程连接服务器,如下图操作:
在这里你可能会遇到无法使用密码登录的问题,首先你要保重重置了实例密码,然后通过 VNC 远程连接,创建 6 位的密码后,进入页面登录实例:
然后按照这个文档 使用密码无法登录 Linux 云服务器 ECS 该如何处理?操作就行了。
重启退出后我们再点远程连接,就可以正常通过密码登录了,然后就可以操作我们的服务器咯。
本机免密登录服务器
如果我们想在自己电脑上就快捷登录到云服务器系统上,可以打开终端,因为我是 Windows 系统,所以使用的是 PowerShell ,然后输入以下命令:
上面
root
是登录用户名,后面的111.11.1.1
是服务器实例的公网 IP,记得替换成你自己的公网 IP。回车之后会让你输入登录密码,即服务器实例密码。但是我们每次打开终端都要执行一遍登录,还要输入密码,特别麻烦,而且不利于后面要讲到的利用 Github Actions 自动化部署的工作进行。
幸运的是可以让本机与云服务器建立信任,实现免密登录,接下来介绍实现建立信任步骤:
本机生成 ssh key
在本机的终端输入以下命令:
云服务器添加本机公钥
执行上面命令以后,要找到
id_rsa.pub
文件,我的电脑上路径是C:\Users\10913\.ssh
,你可以做个参考,然后随便找个编辑器将其打开后,复制该文件内的所有内容,复制到云服务器上的~/.ssh/authorized_keys
文件中(如没有该文件,就创建一个)。上述过程用到步骤命令如下:
然后你输入
exit
命令退出云服务器系统,再重新执行上述登录,就不用输入密码了。如果还是需要你输入密码,估计是权限不够,我们使用密码再次登录后,依次执行以下命令:
安装必要软件
云服务器的初始系统是比较干净的,有些必要的软件需要我们自己安装。比如,开发的服务端没有 Node 怎么那可不行。
在开始安装之前,要确认我们的云服务器能访问外网,简单的方法就是
ping
一下随便一个域名,比如:如果是像下面一样,就代表网是通的。
安装 git
因为我购买云服务器时选择的系统是 CentOS,自带 yum ,所以我可以使用它来安装 git :
安装完成之后,查看 git 版本:
安装 nginx
继续使用 yum 安装:
安装完成之后,查看 nginx 版本:
安装 wget
wget 可以在控台访问一个 url 地址,并得到返回结果,用于下载软件,也可用于测试 web server 是否正常运行。
安装 nvm
nvm 是一个 node 包版本管理工具,非常好用,使用 wget 来安装:
下载的版本最好保持最新,可在 nvm 官方文档 随时查看。
如果你安装成功了之后,需要重新连接服务器,查看 nvm 版本:
安装 node
有了 nvm,可以很方便地安装 node 的不同版本,因为我本地开发项目时 node 版本是
16.19.0
,所以为了保持一致,我准备在云服务器上也安装一个相同的版本。 执行以下命令以查看 node 版本有哪些:然后选一个版本开始安装:
安装成功之后确认下:
查看当前使用的 node 版本:
安装 yarn
因为我使用的时 yarn 包管理器,需要安装下:
查看当前使用的 yarn 版本:
安装 pm2
使用 npm 直接安装 pm2 :
查看当前使用的 pm2 版本:
测试 web 和 node 服务
必须的环境准备好之后,我们需要确认公网是否能访问我们的服务器资源,所以需要先写个测试的 demo 。
新建静态页面
在根目录下,新建一个测试目录,进入该目录:
然后在该目录下新建一个 html ,并编辑:
编辑内容如下:
找到 nginx 配置文件进行配置
执行以下命令查看
nginx.conf
的所在位置:直接开始编辑:
添加一个
server
::wq
保存退出之后,再执行下nginx -t
看是否正常。如果正常,重启下 nginx :然后使用 wget 测试下是否能正常访问该目录下的资源:
结果报了 403 的错误,表示没有相关权限,我们去修改
nginx.conf
文件,把user nginx
改成user root
就可以了。创建 node 服务
我们再试一下使用 pm2 启动一个 node 服务。首先来到
test-demo
下新建一个server.js
:编辑该 js 文件并输入以下内容:
保存退出后启动 node 服务:
使用 wget 测试服务是否启动成功:
执行之后会默认下载一个
index.html
文件,我们查看下它的里面是什么内容:如果输出了以下内容就代表我们的服务启动了:
公网访问
云服务器是有一个公网 IP 的,这意味着我们可以在公网访问其服务器资源,但是需要配置防火墙。 我们可以先尝试访问下公网 IP 获取上面创建的
test.html
,在浏览器打开以下地址(记得替换你的公网 IP):或者上面创建的 node 服务:
不出意外的话,是完全不可访问的。需要回到阿里云平台配置安全组开放我们的端口,如下图:
现在再访问应该就可以了。
Github Actions 自动部署
每次发布新的代码都要登录到服务器,手动部署最新的代码,这是重复且容易犯错的一个过程,如果我们能让机器自己执行这个过程,大大降低了风险和解放了劳动力。
Github Actions 是 Github 免费提供的一个持续集成服务,接下来介绍如何做。
新建 secrets
之前我们说过本机与远程的云服务器建立了信任得以免密登录,现在我们使用 Github Actions 提供的临时的虚拟机也就相当于我们的本机,也要建立信任,才能方便进行后续文件拷贝的工作。
还记得之前已经我们的公钥(即
id_rsa.pub
)添加到云服务器,如果我们把本机的私钥(即id_rsa
)搬到虚拟机上,不就可以模拟本机免密登录了吗!来到我们的 github 项目下,找到以下新建
secret
的地方,新建一个私钥的secret
:切记,私钥一定不能泄露,不然别人能随便就登进你的服务器了。
成功之后如下图,另外我还建了其它的
secret
,服务器的公网 IP 和项目目录地址。编写 workflow
现在我先部署我的
type-room-web
前端项目。在项目的根目录下新建
.github
目录,再新建workflows
目录,最后在新建deploy.yml
文件,编辑这个文件:总结下上面文件做的事情:
main
分支的提交后,且src/**
等文件内容改变时,开始执行这次 ci 流程;secrets
中的建立的私钥写入到虚拟机的.ssh/id_rsa
中,并赋予读的权限,再将云服务器的公网 IP 追加写入到.ssh/known_hosts
中;dist
目录复制到云服务器对应目录;⚠️ 这里请务必注意,你要事先在云服务器上建好你要操作的目录,比如我的
/root/type-room/web
。 万事俱备,现在让我们提交一波前端的项目看看:修改 nginx.conf
因为现在用到的是我们实际的项目,所以需要修改之前的 nginx 配置文件:
如果顺利的话,你会看到每一步都是 OK 的,如果遇到了问题,不要慌,根据错误提示去解决,放心,不难的。
购买数据库
我购买的是下面这个,新人专享还是蛮便宜的:
数据库连接
连接数据库
首先要来到我们购买的数据库控制台,点击实例进入后来到账号管理,创建一个主账号:
然后就可以用这个账号登录数据库了:
本机连接数据库
目前只能通过阿里云自研的 DMS 进行数据库管理,如果你想在自己常用的电脑上连接远程数据库,需要开放外网访问,且要给自己的本机 IP 加白名单。
等待一会儿后,点击外网地址旁边的设置白名单,添加一个白名单组,把你的本机出口 IP 地址添加上去:
⚠️ 也可以再新建一个安全组,专门放你的云服务器内网和外网地址,这样后续可以通过内网连接数据库。
这一步做完,就可以在本机连接我们的远程是数据库了,比如我使用 MySQL Workbench 来进行连接:
node 项目修改数据库连接地址
来到我们的 node 服务端项目,你必然是会有一个数据库连接地址的,将其修改为云数据库的内网地址:
部署 node 服务
在项目根目录下新建
ecosystem.config.js
文件,写入 pm2 所需的配置:增加
package.json
中的生产环境启动服务命令prod
:和前端项目一样,也要创建我们的
.github/workflows/deploy.yml
,写入以下内容:和 web 项目不一样的是,复制时使用的是
scp
,现在我们用的是rsync
,两者区别大家可以自行查查。然后我们提交代码到 github 远程仓库,在 actions 里面看下我们的 ci 流程是否正常。
创建数据库
现在 node 服务是部署好了,我们可以登录云数据库,创建数据库,我的创建格式如下:
创建好数据库,我需要去创建和我开发环境保持一直的数据库表,因为我用的是
sequelize
,我在云服务器的 node 项目根目录下执行下写有同步逻辑的 js 文件就可以了。比如我的同步操作:同步成功之后,就可以开始读写数据库了,截止目前,你的 web 和 node 项目都已经完成了线上自动化部署、公网访问的所有流程了。
域名解析
现在访问我们的页面只能通过服务器的公网 IP 去访问,我们希望通过自己购买的域名去进行访问,该怎么做呢? 首先,找到域名解析,你会看到你购买的域名:
在列表的最右边有解析设置按钮,点击跳转之后,再点击新手引导,填入以下信息:
记住要把对应设置"@"主机记录和对应设置"www"主机记录都勾选上,前者可以让你不输入
www
时也能正常访问。设置之后我们打开终端,测试下域名的连通性,我们 ping 一下域名:
如果能正确显示出云服务器的 IP 地址表示成功了:
这个时候,已经可以使用域名代替之前的公网 IP 访问了,就像我的这样:
默认 80 端口
细心的同学会发现,我现在访问页面还需要加端口
8088
才行,这是因为我云服务器的 nginx 配置中将前端资源的server
端口设置成了8088
,将它改成80
端口:回到阿里云服务器实例的控制台,将安全组规则中原来的
8088
改成80
:改完之后再访问我们的页面,即不加端口的地址:
结果出现这个提示:
原因时我们的网站没有进行备案,那接下来就去备案呗~
网站备案
访问阿里云网站备案,按照流程填写资料,提交申请后只能等待了。
如果你的居住地和户籍地不一致,要事先去办理流动人口居住证,阿里云那边审核的时候肯定会给你打电话的,所以事先准备好吧。
后续如果一切顺利的话,你的域名就可以正常访问了。
支持 https 访问
https 想必 http 的优势是什么就不说了,老生常谈了,你的网站如果不是 https,在如今,对你的访问量几乎是打击性的。
但是付费的 SSL 证书是真的贵!接下来为大家演示下如何申请免费的证书,并让你的网站支持 https 访问。这一切得益于 Let's Encrypt 免费证书 。
安装 certbot
Certbot 是 Let's Encrypt 推出的获取证书的客户端,可以让我们免费快速地获取 Let's Encrypt 证书。
先安装必要的软件:
生成证书
接着生成泛域名证书(别忘了写的是你自己的域名哦):
执行上面命令后会连续回答几个问题,该填邮箱就填,该同意的就同意,直到出现这个提示:
回到阿里云域名解析,添加一条
TXT
的解析:添加完解析后稍等几秒钟,即可回车继续,这时候就会校验记录是否有效。
出现这个 Congratulations 就算是成功了!!生成的证书在
/etc/letsencrypt/live
目录下。修改 nginx 配置
原来 http 访问的是
80
端口,我们需要修改为443
端口,并增加证书的配置:修改配置之后要重启下 nginx :
开放 443 端口
之前云服务器的安全组配置是开放了
80
端口,现在需要新增一个443
端口。不出意外的话,现在你可以使用 https 访问你的网站了!但是意外总会出现,比如访问 https 还是不通。但是我们不慌,一步一步解决。
可先通过以下命令查看 nginx 进程的 pid 和监听的端口:
发现已经监听
80
和443
了:我们先看下 nginx 服务的状态:
结果报红了:
重启 nginx 也是失败:
百般不得其解,直到看到这个问题:
nginx.service failed because the control process exited
最高赞的回答解决了这个问题,首先找到当前占用了
80
和443
端口的进程,发现就是 nginx 的:然后根据
pid
(比如 9680)杀掉这个进程:这个时候再重启 nginx 服务就可以了:
自动续期
免费证书有效期 3 个月,到期之后我们可以再次续期,达到永久免费的效果。
https://www.frankfeekr.cn/2021/03/28/let-is-encrypt-cerbot-for-https/index.html https://juejin.cn/post/7205839782381928508#comment
github host
阿里云的国内服务器,访问 github 时经常访问不到,可以尝试修改下本地的 hosts,但是 github 的访问 ip 经常变动,每次都要手动去更新 ip。
好在有 GitHub520 这个项目,让我们写个定时任务,实时拿最新的 ip 写入到系统的 hosts 配置文件中,比如 CentOS 下是
/etc/hosts
。首先写入一个定时任务:
另起一行后,写入以下内容:
每个 1 天就会去获取最新的数据进行写入。
:wq
保存之后重启下crontab
服务:大功告成!