Hexo博客迁移至CNB自动部署
背景
本文记录了将Hexo博客从传统Docker部署方案迁移至CNB(Cloud Native Build)自动部署平台的完整过程,包括遇到的问题和解决方案。
原先部署方案
部署架构
原先使用GitLab CI/CD + Docker的自动化部署方式:
构建环境:基于GitLab CI/CD的自动化构建
构建流程:
- 当Dockerfile变更时触发构建阶段
- 使用Docker构建包含Node.js和Hexo的镜像
- 推送镜像到私有镜像仓库
- 当相关文件变更时触发部署阶段
- 通过SSH连接到服务器执行git pull
- 使用docker-compose拉取新镜像并重新创建容器
部署方式:通过GitLab CI/CD自动部署到服务器Docker环境
原有Dockerfile结构
1 | FROM node |
原有GitLab CI/CD配置
1 | # .gitlab-ci.yml |
存在的问题
- 基础设施依赖:需要维护GitLab Runner和私有镜像仓库
- 构建资源消耗:每次构建都需要完整的Docker镜像构建过程
- 部署复杂性:需要配置SSH密钥、Docker context等多个组件
- 维护成本高:需要管理GitLab CI/CD环境和相关基础设施
现在的CNB部署方案
CNB平台优势
CNB(Cloud Native Build)是腾讯云提供的云原生构建平台,具有以下优势:
- 全托管的CI/CD环境
- 支持多种构建环境和插件
- 与Git仓库深度集成
- 支持自动触发和部署
新的部署架构
1 | # .cnb.yml配置文件 |
迁移过程中的主要改变
1. 构建环境变化
- 原先:GitLab CI/CD + Docker镜像构建
- 现在:CNB云端直接构建,无需Docker镜像
2. 部署流程优化
- 原先:Docker镜像推送→服务器拉取→容器重建
- 现在:静态文件生成→rsync直接同步到nginx目录
3. 配置管理
- 原先:配置文件分散在不同位置
- 现在:集中在config目录,便于管理
3. 基础设施简化
- 原先:需要维护GitLab Runner、私有镜像仓库、Docker环境
- 现在:只需CNB平台,无额外基础设施
4. 主题管理
- 原先:通过git clone获取主题
- 现在:将主题文件直接包含在项目中
5. 部署目标变化
- 原先:部署到Docker容器,通过端口4000提供服务
- 现在:直接部署静态文件到nginx目录,性能更优
遇到的问题及解决方案
1. YAML语法错误
问题描述:
1 | YAMLException: bad indentation of a mapping entry |
原因:sed命令中包含特殊字符和中文,YAML解析器无法正确处理
解决方案:
1 | # 错误写法 |
使用双引号包裹整个命令,内部使用转义字符处理特殊字符。
2. Nginx 404错误和重定向循环
问题描述:
1 | rewrite or internal redirection cycle while internally redirecting to "/index.html" |
原因:Hexo站点缺少必要的页面(categories、tags、about),导致Next主题出现内部重定向循环
解决方案:
在构建过程中添加页面初始化步骤:
1 | hexo new page categories |
3. 构建顺序问题
问题描述:构建时找不到配置文件或主题文件
解决方案:
调整构建步骤顺序,确保在初始化页面前先复制所有必要文件:
- 复制主题文件到themes目录
- 复制博客文章到source/_posts
- 复制配置文件
- 初始化页面
- 构建生成静态文件
4. 权限和密钥管理
问题描述:rsync部署时需要SSH私钥认证
解决方案:
- 使用CNB的密钥仓库功能存储敏感信息
- 通过环境变量
${SSH_PRIVATE_KEY}引用私钥 - 配置imports字段导入环境变量
5. Nginx配置问题
5.1 Docker挂载路径不一致
问题描述:
1 | "/app/chlm-nginx/html/blog/index.html" is not found (2: No such file or directory) |
原因:nginx配置中使用的路径与docker-compose.yml中的挂载路径不一致
1 | # docker-compose.yml |
但nginx配置中使用了错误路径:
1 | root /app/chlm-nginx/html/blog; # 错误路径 |
解决方案:
修正nginx配置中的路径:
1 | location / { |
5.2 目录访问403错误
问题描述:
1 | directory index of "/home/chlm/html/blog/categories/" is forbidden |
原因:访问目录时nginx尝试列出目录内容而不是查找index.html
解决方案:
使用正确的try_files配置:
1 | location / { |
5.3 try_files配置导致的重定向循环
问题描述:
1 | rewrite or internal redirection cycle while internally redirecting to "/index.html" |
原因:不当的try_files配置导致无限重定向
常见错误配置:
1 | # 错误:会导致循环重定向 |
正确配置:
1 | # 正确:避免循环重定向 |
5.4 Hexo博客的完整nginx配置
最终优化配置:
1 | location / { |
注意:不要添加静态资源过滤规则,会与其他服务冲突:
1 | # ❌ 错误:不要添加这样的配置 |
原因:
- 图片等静态资源可能由其他服务处理(如MinIO对象存储)
- 过度的location匹配会导致路径冲突
- 应该让专门的服务处理对应的资源类型
5.5 Nginx核心指令详解
root vs alias 的区别
root指令:
- 定义文档根目录,会将location路径附加到root路径后面
- 适用于大多数静态文件服务场景
1 | # 访问 /blog/index.html 会查找 /var/www/blog/index.html |
alias指令:
- 定义路径替换,直接将location路径替换为alias路径
- 适用于需要路径映射的场景
1 | # 访问 /blog/index.html 会查找 /var/www/hexo/index.html |
选择原则:
- 当URL路径与文件系统路径结构一致时使用
root - 当需要将URL路径映射到不同的文件系统路径时使用
alias
try_files指令详解
作用:按顺序尝试多个文件/URI,直到找到存在的文件或执行fallback
语法:try_files file1 file2 ... uri;
常见用法场景:
静态网站路径重写(如Hexo博客):
1
2
3
4
5
6try_files $uri $uri/ $uri/index.html =404;
# 访问 /categories/ 时:
# 1. 先找 /categories/ 文件(通常不存在)
# 2. 再找 /categories/ 目录(存在但是目录)
# 3. 再找 /categories/index.html(Hexo生成的页面)
# 4. 都找不到返回404SPA应用路由支持:
1
2try_files $uri $uri/ /index.html;
# 对于Vue/React等SPA应用,所有路由都回退到index.html多语言站点回退:
1
2try_files $uri $uri/ /zh/index.html /en/index.html =404;
# 按语言优先级依次尝试缓存穿透处理:
1
2try_files $uri @backend;
# 静态文件不存在时转发到后端服务
什么情况需要try_files
必须使用try_files的场景:
静态网站生成器(Hexo/Hugo/Jekyll等):
- URL结构:
/categories/ - 文件结构:
/categories/index.html - 需要try_files处理目录到文件的映射
- URL结构:
单页应用(SPA):
- 前端路由:
/user/profile - 实际文件:只有
/index.html - 需要所有路由都回退到index.html
- 前端路由:
伪静态URL:
- 用户友好URL:
/article/123 - 实际处理:
/article.php?id=123
- 用户友好URL:
不需要try_files的场景:
- 纯静态文件服务:文件路径与URL完全对应
- 纯代理服务:所有请求都转发到后端
- API服务:每个endpoint都有明确的处理逻辑
Hexo博客为什么需要try_files
1 | try_files $uri $uri/ $uri/index.html =404; |
原因分析:
URL美化:Hexo生成美化的URL结构
- 访问:
https://blog.com/categories/ - 文件:
/categories/index.html
- 访问:
目录结构映射:
/→/index.html/categories/→/categories/index.html/archives/2025/→/archives/2025/index.html
兼容性处理:同时支持带trailing slash和不带的URL
5.6 调试技巧
查看目录结构:
1 | # 安装tree工具 |
nginx日志分析:
1 | # 实时查看错误日志 |
try_files调试:
1 | # 临时添加调试日志 |
最佳实践建议
1. 配置文件管理
- 将所有配置文件集中存放在config目录
- 使用版本控制跟踪配置变更
- 敏感信息使用环境变量管理
2. 构建优化
- 使用volumes缓存npm包和node_modules
- 选择合适的基础镜像(如node:18-alpine)
- 合理安排构建步骤顺序
3. 部署策略
- 使用rsync进行增量同步
- 配置部署前后的检查脚本
- 保留部署日志便于问题排查
4. 问题排查
- 关注CNB构建日志
- 检查YAML语法格式
- 验证文件路径和权限
- 测试nginx配置
总结
通过将Hexo博客迁移至CNB平台,实现了:
- 自动化部署:Git推送即可触发构建和部署
- 环境一致性:云端标准化构建环境
- 操作简化:减少了手动操作步骤
- 可维护性:配置文件化,便于版本管理
迁移过程中主要的挑战在于YAML配置语法和Hexo页面初始化,通过合适的转义和构建步骤安排成功解决。CNB平台为静态博客提供了一个高效、稳定的自动化部署解决方案。