使用 GitHub Actions 自动部署 Astro 博客到宝塔面板
📖 前言
在开发博客的过程中,每次更新内容都需要手动构建、上传到服务器,这个过程重复且耗时。本文记录了如何使用 GitHub Actions 实现自动化部署流程:只需 git push,代码就能自动构建并部署到生产环境。
技术栈:
- 前端框架:Astro v4.x
- 版本控制:Git + GitHub
- CI/CD:GitHub Actions
- 服务器:阿里云 ECS + 宝塔面板
- 部署方式:FTP
🎯 实现目标
本地修改代码 → git push → GitHub Actions 自动构建 → FTP 上传 → 网站更新 ✅
整个过程无需人工干预,推送代码后 2-3 分钟内网站自动更新。
🛠️ 实现步骤
第一步:配置 GitHub Actions Workflow
在项目根目录创建 .github/workflows/deploy.yml:
name: Build and Deploy to Baota
on:
push:
branches:
- main # 监听 main 分支的推送
workflow_dispatch: # 允许手动触发
jobs:
build-and-deploy:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: "☁️ Checkout repository"
uses: actions/checkout@v4
- name: "🔧 Setup Node.js"
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- name: "📦 Install dependencies"
run: npm ci
- name: "🚀 Build the project"
run: npm run build
- name: "📤 Deploy to FTP Server"
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: \${{ secrets.FTP_SERVER }}
username: \${{ secrets.FTP_USERNAME }}
password: \${{ secrets.FTP_PASSWORD }}
local-dir: ./dist/
server-dir: /
dangerous-clean-slate: false
timeout: 300000
配置说明:
on.push.branches:指定触发分支npm ci:使用 lockfile 安装依赖(比npm install更快更可靠)cache: "npm":缓存 node_modules,加速构建timeout: 300000:设置 5 分钟超时,防止大文件传输失败
第二步:配置宝塔面板 FTP
2.1 创建 FTP 账号
- 登录宝塔面板(默认端口 8888)
- 进入 FTP → 添加 FTP
- 填写配置:
- 用户名:
your_ftp_username - 密码:生成强密码
- 根目录:选择网站目录(如
/www/wwwroot/www.lab.withyunhan.com) - 权限:读写
- 用户名:
2.2 配置 FTP 被动模式(重要!)
这是解决 GitHub Actions 连接超时的关键步骤:
- 软件商店 → Pure-Ftpd → 设置
- 找到「被动端口范围」配置
- 设置端口范围:
39000-40000 - 重启 Pure-Ftpd 服务
2.3 开放防火墙端口
宝塔面板防火墙:
- 安全 → 添加端口规则
- 端口范围:
39000:40000 - 协议:TCP
- 备注:FTP 被动模式端口
阿里云安全组(如使用阿里云):
- 登录阿里云控制台
- ECS → 网络与安全 → 安全组
- 配置规则 → 添加入方向规则
- 端口范围:
39000/40000,协议:TCP
第三步:配置 GitHub Secrets
GitHub Secrets 用于安全存储敏感信息(密码、密钥等)。
3.1 进入 Secrets 配置页面
访问:https://github.com/你的用户名/你的仓库名/settings/secrets/actions
或通过页面导航:
仓库 → Settings → Secrets and variables → Actions → New repository secret
3.2 添加三个 Secret
| Name | Value | 说明 |
|---|---|---|
FTP_SERVER | 123.45.67.89 | 服务器 IP 或域名 |
FTP_USERNAME | your_ftp_username | FTP 用户名 |
FTP_PASSWORD | your_ftp_password | FTP 密码 |
注意:Secret 添加后无法查看,只能重新设置。
第四步:统一包管理器
本项目原使用 pnpm,但本地使用 npm,导致 lockfile 不同步。
问题现象
GitHub Actions 报错:
ERR_PNPM_OUTDATED_LOCKFILE Cannot install with "frozen-lockfile"
because pnpm-lock.yaml is not up to date with package.json
解决方案
方式一:统一使用 npm(已采用)
- 删除
pnpm-lock.yaml - 修改 workflow 使用
npm ci - 确保
package-lock.json存在且最新
# 删除 pnpm lockfile
Remove-Item pnpm-lock.yaml
# 生成新的 npm lockfile
npm install
# 提交更改
git add .
git commit -m "切换到 npm 包管理器"
git push
方式二:统一使用 pnpm
本地也改用 pnpm:
npm install -g pnpm
pnpm install # 更新 pnpm-lock.yaml
🚀 部署测试
首次部署
提交代码触发自动部署:
git add .
git commit -m "配置 GitHub Actions 自动部署"
git push origin main
查看部署状态
- 访问仓库的 Actions 页面
- 点击最新的 workflow 运行记录
- 实时查看各步骤执行情况
预期结果:
- ✅ Checkout repository
- ✅ Setup Node.js
- ✅ Install dependencies (17s)
- ✅ Build the project (20s)
- ✅ Deploy to FTP Server (60-120s)
🐛 常见问题排查
问题 1:FTP 数据连接超时
错误信息:
Error: Timeout when trying to open data connection to 8.141.119.157:39484
原因:FTP 被动模式端口未开放。
解决方案:
- 检查 Pure-Ftpd 被动端口配置(如 39000-40000)
- 确认宝塔防火墙已开放该端口
- 确认云服务商安全组已开放该端口
问题 2:lockfile 不同步
错误信息:
ERR_PNPM_OUTDATED_LOCKFILE
解决方案: 统一包管理器(npm 或 pnpm),删除旧 lockfile,重新生成并提交。
问题 3:构建失败
错误信息:
Module not found
解决方案:
- 本地测试
npm run build是否成功 - 检查
package.json中 dependencies 是否完整 - 确保 lockfile 已提交到仓库
问题 4:部署后 404
可能原因:
- FTP
server-dir配置错误 - 宝塔网站根目录配置不匹配
解决方案:
检查 workflow 中的 server-dir 是否与 FTP 根目录一致。
🔧 高级配置
1. 部署到子目录
如果需要部署到网站的子目录(如 /blog/):
- name: "📤 Deploy to FTP Server"
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server-dir: /blog/ # 相对于 FTP 根目录
2. 排除特定文件
不上传某些文件:
- name: "📤 Deploy to FTP Server"
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
exclude: |
**/.git*
**/.git*/**
**/node_modules/**
.env
3. 清空服务器目录
⚠️ 危险操作,会删除服务器所有文件:
dangerous-clean-slate: true
建议仅在首次部署使用,之后改为 false 实现增量更新。
4. 多环境部署
配置不同分支部署到不同环境:
on:
push:
branches:
- main # 生产环境
- develop # 开发环境
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# ... 构建步骤
- name: "📤 Deploy to Production"
if: github.ref == 'refs/heads/main'
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: \${{ secrets.PROD_FTP_SERVER }}
# ...
- name: "📤 Deploy to Development"
if: github.ref == 'refs/heads/develop'
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: \${{ secrets.DEV_FTP_SERVER }}
# ...
📊 性能优化
1. 缓存依赖
已在 workflow 中配置:
- name: "🔧 Setup Node.js"
uses: actions/setup-node@v4
with:
cache: "npm" # 缓存 node_modules
效果:第二次构建时依赖安装时间从 17s 降至 3-5s。
2. 增量部署
FTP-Deploy-Action 默认智能检测文件变更:
- 只上传修改过的文件
- 不会重复上传未改变的文件
- 自动计算文件哈希值
首次部署:上传 133 个文件,耗时 60-120s
后续部署:仅上传 2-5 个文件,耗时 10-20s
3. 并行构建
如果有多个任务可以并行执行:
jobs:
build:
# 构建任务
test:
# 测试任务(并行执行)
deploy:
needs: [build, test] # 等待 build 和 test 完成
# 部署任务
🔐 安全建议
-
永远不要在代码中硬编码密码
- 使用 GitHub Secrets 存储敏感信息
- 确保
.env文件在.gitignore中
-
定期更换密码
- FTP 密码建议每 3-6 个月更换
- 使用强密码(大小写+数字+符号)
-
最小权限原则
- FTP 账号仅授予必要目录的读写权限
- 不要使用 root 用户
-
启用 HTTPS
- 确保网站配置了 SSL 证书
- 宝塔面板可免费申请 Let’s Encrypt 证书
📈 监控与通知
添加部署通知
在 workflow 中添加成功/失败通知:
- name: "✅ Deploy Success"
if: success()
run: |
echo "🎉 部署成功!"
echo "网站地址: https://www.lab.withyunhan.com"
- name: "❌ Deploy Failed"
if: failure()
run: |
echo "部署失败,请检查日志"
exit 1
集成消息推送(可选)
可以接入:
- 企业微信机器人
- 钉钉机器人
- Slack
- Telegram Bot
🎓 学到的经验
1. 包管理器要统一
本地、CI/CD 环境必须使用同一个包管理器(npm/pnpm/yarn),否则 lockfile 会不同步。
2. FTP 被动模式的坑
GitHub Actions 服务器位于海外,必须配置 FTP 被动模式并开放端口,否则数据连接会超时。
3. 增量部署很重要
首次部署后,后续部署只更新变化的文件,极大提升了部署速度。
4. lockfile 必须提交
package-lock.json 或 pnpm-lock.yaml 必须提交到 Git,确保依赖版本一致。
🚀 总结
通过 GitHub Actions 配置自动化部署后:
部署前:
- 本地
npm run build(20s) - FTP 工具连接服务器(手动)
- 上传 dist 目录(2-3 分钟)
- 刷新浏览器验证
部署后:
git push(3s)- 等待 2 分钟
- 自动完成 ✅
节省了大量重复劳动,可以专注于内容创作和功能开发。
📚 参考资源
💬 后记
自动化部署是现代 Web 开发的标配。虽然配置过程中遇到了一些问题(锁文件不同步、FTP 超时等),但解决后极大提升了开发效率。希望这篇文章能帮助你快速搭建自己的 CI/CD 流程!
如有问题或建议,欢迎在评论区交流。🎉