Skip to content
Yunhan's Lab
Go back

使用 GitHub Actions 自动部署 Astro 博客到宝塔面板

Edit page

使用 GitHub Actions 自动部署 Astro 博客到宝塔面板

📖 前言

在开发博客的过程中,每次更新内容都需要手动构建、上传到服务器,这个过程重复且耗时。本文记录了如何使用 GitHub Actions 实现自动化部署流程:只需 git push,代码就能自动构建并部署到生产环境。

技术栈


🎯 实现目标

本地修改代码 → 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

配置说明


第二步:配置宝塔面板 FTP

2.1 创建 FTP 账号

  1. 登录宝塔面板(默认端口 8888)
  2. 进入 FTP添加 FTP
  3. 填写配置:
    • 用户名:your_ftp_username
    • 密码:生成强密码
    • 根目录:选择网站目录(如 /www/wwwroot/www.lab.withyunhan.com
    • 权限:读写

2.2 配置 FTP 被动模式(重要!)

这是解决 GitHub Actions 连接超时的关键步骤:

  1. 软件商店Pure-Ftpd设置
  2. 找到「被动端口范围」配置
  3. 设置端口范围:39000-40000
  4. 重启 Pure-Ftpd 服务

2.3 开放防火墙端口

宝塔面板防火墙

  1. 安全添加端口规则
  2. 端口范围:39000:40000
  3. 协议:TCP
  4. 备注:FTP 被动模式端口

阿里云安全组(如使用阿里云):

  1. 登录阿里云控制台
  2. ECS网络与安全安全组
  3. 配置规则添加入方向规则
  4. 端口范围: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

NameValue说明
FTP_SERVER123.45.67.89服务器 IP 或域名
FTP_USERNAMEyour_ftp_usernameFTP 用户名
FTP_PASSWORDyour_ftp_passwordFTP 密码

注意: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(已采用)

  1. 删除 pnpm-lock.yaml
  2. 修改 workflow 使用 npm ci
  3. 确保 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

查看部署状态

  1. 访问仓库的 Actions 页面
  2. 点击最新的 workflow 运行记录
  3. 实时查看各步骤执行情况

预期结果


🐛 常见问题排查

问题 1:FTP 数据连接超时

错误信息

Error: Timeout when trying to open data connection to 8.141.119.157:39484

原因:FTP 被动模式端口未开放。

解决方案

  1. 检查 Pure-Ftpd 被动端口配置(如 39000-40000)
  2. 确认宝塔防火墙已开放该端口
  3. 确认云服务商安全组已开放该端口

问题 2:lockfile 不同步

错误信息

ERR_PNPM_OUTDATED_LOCKFILE

解决方案: 统一包管理器(npm 或 pnpm),删除旧 lockfile,重新生成并提交。

问题 3:构建失败

错误信息

Module not found

解决方案

  1. 本地测试 npm run build 是否成功
  2. 检查 package.json 中 dependencies 是否完整
  3. 确保 lockfile 已提交到仓库

问题 4:部署后 404

可能原因

  1. FTP server-dir 配置错误
  2. 宝塔网站根目录配置不匹配

解决方案: 检查 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 完成
    # 部署任务

🔐 安全建议

  1. 永远不要在代码中硬编码密码

    • 使用 GitHub Secrets 存储敏感信息
    • 确保 .env 文件在 .gitignore
  2. 定期更换密码

    • FTP 密码建议每 3-6 个月更换
    • 使用强密码(大小写+数字+符号)
  3. 最小权限原则

    • FTP 账号仅授予必要目录的读写权限
    • 不要使用 root 用户
  4. 启用 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

集成消息推送(可选)

可以接入:


🎓 学到的经验

1. 包管理器要统一

本地、CI/CD 环境必须使用同一个包管理器(npm/pnpm/yarn),否则 lockfile 会不同步。

2. FTP 被动模式的坑

GitHub Actions 服务器位于海外,必须配置 FTP 被动模式并开放端口,否则数据连接会超时。

3. 增量部署很重要

首次部署后,后续部署只更新变化的文件,极大提升了部署速度。

4. lockfile 必须提交

package-lock.jsonpnpm-lock.yaml 必须提交到 Git,确保依赖版本一致。


🚀 总结

通过 GitHub Actions 配置自动化部署后:

部署前

  1. 本地 npm run build(20s)
  2. FTP 工具连接服务器(手动)
  3. 上传 dist 目录(2-3 分钟)
  4. 刷新浏览器验证

部署后

  1. git push(3s)
  2. 等待 2 分钟
  3. 自动完成 ✅

节省了大量重复劳动,可以专注于内容创作和功能开发。


📚 参考资源


💬 后记

自动化部署是现代 Web 开发的标配。虽然配置过程中遇到了一些问题(锁文件不同步、FTP 超时等),但解决后极大提升了开发效率。希望这篇文章能帮助你快速搭建自己的 CI/CD 流程!

如有问题或建议,欢迎在评论区交流。🎉


Edit page
Share this post on:

Previous Post
Fibonacci-like 6步走
Next Post
设计模式对比(优缺点)