该文章的 Shell 脚本部分过于冗余,若需要看更简约更直观的,可查看 Github Action 实现 CI CD 自动化部署
使用 Github Action 的原因是,jenkins 占用的服务器资源较多,低配置服务器 jenkins 很容易资源打满。
Table of contents
Open Table of contents
了解 Github Action
什么是 GitHub Action?其实也很容易理解,如果你用过 github pages 或者 vercel 的话就不陌生,就是一个 CI/CD 服务。提交代码自动触发部署。那么如何让 github action 连接远程服务器触发部署呢?
网上大部分的教程都是基于 ssh + docker 部署的,说实在,目前有点玩不转 docker,所以已有的思路是:
- 本地代码提交
- 触发 GitHub Action
- 执行构建脚本(git pull、install、build 等)
其实脚本构建这一步和 Dockerfile 是一样的思路。
SSH 连接服务器
GitHub 需要的配置
使用 ssh 连接 服务器,需要 ssh 私钥,但是私钥不能直接写入配置文件,GitHub 提供了相关功能,可以理解为 env。
点击项目仓库的 Settings -> Secrets and variables -> Actions -> new repository secret,填入 key 和 value,多个 secret 需要多次创建,在 GitHub Action 中访问时以 object 对象格式访问。跟 js 的对象语法类似。key 就是对象 key,value 就是 对应的值。

比如
new repository secret时添加了 keySSH_PRIVATE_KEY,那么在 GitHub Action 中访问时,就使用${{ secrets.SSH_PRIVATE_KEY }}。
生成 SSH
ssh 公私钥在 ~/.ssh 下,可以 cd 到该目录下 ls 查看。
如果只有一个 authorized_keys,则需要使用 ssh-keygen 生成公私钥对。具体步骤如下
ssh-keygen -t rsa -C "github action"生成公私钥对- 其中
-C "github action"类似备注,可以省略
- 其中
- 生成成功后
ls查看,此时应该有三个文件id_rsa、id_rsa.pub、authorized_keys cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys,设置公钥内容为authorized_keys文件的内容,cat ~/.ssh/id_rsa将私钥内容添加到 GitHub 仓库的 Secret 中。
编写 Github Action
此处提供一个 nest 服务的 GitHub Action 示例:
在 项目根目录新建 .github/workflows/deploy.yml 文件,内容如下
name: Deploy-nest
on:
push:
branches:
- server
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: ssh connect server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }} # ip address
username: ${{ secrets.SSH_USER }} # server username
key: ${{ secrets.SSH_PRIVATE_KEY }} # server ssh private key
- name: Run Script to Deploy serve
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
SERVER_PATH_REMOTE: ${{ secrets.SERVER_PATH_REMOTE }}
APP_NAME: nest-oss
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan $SSH_HOST >> ~/.ssh/known_hosts
ssh $SSH_USER@$SSH_HOST << EOF
cd $SERVER_PATH_REMOTE
MAX_RETRIES=8
RETRY_COUNT=0
while [ \$RETRY_COUNT -lt \$MAX_RETRIES ]; do
if git pull origin server; then
break # pull succesful exit
else
echo "Git pull failed, retrying (\$((RETRY_COUNT + 1)) of \$MAX_RETRIES)..."
((RETRY_COUNT++))
sleep 5
fi
done
# check if retry count exceeded
if [ \$RETRY_COUNT -eq \$MAX_RETRIES ]; then
echo "Failed to pull code after \$MAX_RETRIES attempts. Exiting."
exit 1 # throw error
fi
npm install
npm run build
pm2 restart $APP_NAME || pm2 start dist/src/main.js --name $APP_NAME
EOF
最重要的就是
Deploy to server这个阶段的脚本。简单来说就是连接远程服务器,进入项目目录,执行安装运行脚本,其实就跟正常开发使用命令差不多了,值得注意的是git pull阶段增加了错误重试机制,因为国内服务器直接拉取 GitHub 代码失败率较高。
服务器配置
安装 git node pm2
由于有 node 服务,所以需要 node 和 pm2 来管理,如果项目为 java 或者其它,也是同理配置好环境即可。
- 安装 git
yum install gitgit config --global user.name "youer username"git config --global user.email "your email"git --version检查 git 是否安装成功
如果无法连接 github,可在 /etc/hosts 添加如下代码
52.69.186.44 github.com
151.101.64.133 raw.githubusercontent.com
- 安装 node
- 下载 node16.x gz 压缩包(Centos7 最高支持到 node16)https://registry.npmmirror.com/binary.html?path=node/latest-v16.x/
- 上传到服务器解压
tar -xvf node-v16.x.tar.gz - 配置环境变量:
vi /etc/profile- 添加
export PATH=$PATH/xxx/node16.x/bin source /etc/profile刷新环境变量node -v检查 node 是否安装成功-
其实这里就可以体现出 docker 的好处。直接在服务器安装的话,由于有操作系统版本限制,只能安装某些版本,而用 docker 则无需关心这个问题。
- 添加
- 安装 pm2
npm install pm2 -gpm2 -v检查 pm2 是否安装成功
这种实现方式是通过拉取仓库代码,运行打包脚本,从而达到部署的,因此,安装时的大量
node_modules也会占用大量的空间存储,如果介意此种方式,且项目的运行不需要依托 node,例如前端项目,就可以仅上传 dist 目录即可。
简单运行和停止删除命令如下
pm2 start dist/src/main.js --name nest-osspm2 stop nest-osspm2 delete nest-oss

提交代码
此时提交代码就可以触发 GitHub Action 了。失败的话会有邮箱提示,详细信息可以查看 Action 控制台日志。

SSL 证书
证书相关请查看 免费无限续期 SSL 证书