本文将带你一步步在VPS上部署一个全自动化的Hexo博客,使用Docker运行Nginx,通过Git钩子实现“本地写文章,一键自动部署”。

你是否经历过这样的场景:在本地写好了博客文章,执行hexo generate && hexo deploy,满心期待地打开浏览器,却看到空目录502 Bad Gateway,甚至权限拒绝?别担心,本文将完整记录我搭建博客过程中踩过的每一个坑,以及最终的解决方案。

目录

    1. 整体架构
    1. VPS环境准备(用户与权限)
    1. 配置Git钩子实现自动化部署
    1. Docker Compose部署Nginx
    1. 本地Hexo配置与发布
    1. 踩坑记录与解决方案
    1. 日常更新流程
    1. 结语

1. 整体架构

在开始之前,先理解整个部署链路:

1
2
3
4
5
6
本地Windows (Hexo) 
→ hexo d (git push)
→ VPS Git裸仓库 (触发post-receive钩子)
→ 自动检出文件到网站目录
→ Nginx容器 (通过数据卷挂载)
→ 对外提供服务

这个方案的核心思想是:

  • 解耦:Hexo生成静态文件在本地完成,VPS只负责托管文件。

  • 自动化:利用Git钩子实现“推送即部署”。

  • 容器化:使用Docker Compose管理Nginx,便于迁移和扩展。

2. VPS环境准备(用户与权限)

2.1 创建专用用户

为了安全,我们不使用root用户执行部署任务,而是创建一个专门的git用户:

创建用户并设置密码
1
sudo adduser git

提示:不要将git用户添加到sudo组,遵循最小权限原则。

2.2 配置SSH公钥(免密推送)

将Windows本地的公钥上传到VPS,让git用户可以免密接收推送。

在Windows上生成密钥(如果还没有)

1
ssh-keygen -t rsa -b 4096

一路回车即可,默认保存在C:\Users\你的用户名\.ssh\id_rsa

将公钥添加到VPS

切换到git用户
1
su - git
创建.ssh目录
1
2
mkdir -p ~/.ssh
chmod 700 ~/.ssh
将公钥内容追加到authorized_keys
1
2
echo "你的公钥内容(复制id_rsa.pub的全部内容)" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

验证:在Windows终端执行ssh git@你的VPS_IP,如果无需密码直接登录,说明配置成功。

2.3 创建Git裸仓库

裸仓库(--bare)是Git的“中央服务器”,只存储版本信息,不包含工作目录:

1
2
3
4
su - git
mkdir -p ~/blog.git
cd ~/blog.git
git init --bare

3. 配置Git钩子实现自动化部署

这是整个自动化流程的核心。当git push到达VPS后,post-receive钩子会自动将文件检出到网站目录。

3.1 创建钩子脚本

切换到git用户

1
su - git

编辑钩子文件

1
nano ~/blog.git/hooks/post-receive

写入以下内容(注意替换路径):

1
#!/bin/sh

将文件检出到网站目录

1
git --work-tree=/home/ubuntu/docker/hexo/var/www/html --git-dir=/home/git/blog.git checkout -f

重要--work-tree指向Nginx读取的静态文件目录,--git-dir指向裸仓库位置。

3.2 赋予执行权限

Git只会执行带有可执行权限的钩子文件:bash

1
chmod +x ~/blog.git/hooks/post-receive

3.3 创建网站目录并设置所有权bash

退出git用户,回到root

1
2
3
4
exit
sudo mkdir -p /home/ubuntu/docker/hexo/var/www/html
sudo chown -R git:git /home/ubuntu/docker/hexo/var/www/html
sudo chmod -R 755 /home/ubuntu/docker/hexo/var/www/html

注意:因为网站目录位于/home/ubuntu下,务必确保git用户对该目录有写入权限。


4. Docker Compose部署Nginx

4.1 创建docker-compose.yml

在VPS上创建一个项目目录,例如/home/ubuntu/docker/nginx:bash

1
2
mkdir -p /home/ubuntu/docker/nginx
cd /home/ubuntu/docker/nginx

创建docker-compose.yml

1
2
3
4
5
6
7
8
9
10
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: hexo-nginx
restart: always
ports:
- "88:80" # 宿主机88端口映射到容器80
volumes:
- /home/ubuntu/docker/hexo/var/www/html:/usr/share/nginx/html:ro

4.2 启动容器bash

1
docker-compose up -d

4.3 验证bash

查看容器状态

1
docker ps

查看日志

1
docker logs hexo-nginx

5. 本地Hexo配置与发布

5.1 安装hexo-deployer-git

在Hexo项目根目录下:bash

1
npm install hexo-deployer-git --save

5.2 修改_config.yml

找到deploy字段,配置为:yaml

1
2
3
4
deploy:
type: git
repo: git@你的VPS_IP:/home/git/blog.git
branch: master

5.3 首次部署bash

1
hexo clean && hexo generate && hexo deploy

部署成功后,访问http://你的VPS_IP:88即可看到博客。


6. 踩坑记录与解决方案

6.1 部署后网站目录为空

现象hexo d执行成功,但/home/ubuntu/docker/hexo/var/www/html目录下没有任何文件。

原因post-receive钩子文件没有可执行权限,或被git用户无法写入目标目录。

解决方案

bash

赋予钩子执行权限

1
2
su - git
chmod +x ~/blog.git/hooks/post-receive

确保git用户对网站目录有写权限

1
2
sudo chown -R git:git /home/ubuntu/docker/hexo/var/www/html
sudo chmod -R 755 /home/ubuntu/docker/hexo/var/www/html

验证方法:手动以git用户执行钩子命令,观察报错。bash

1
2
su - git
git --work-tree=/home/ubuntu/docker/hexo/var/www/html --git-dir=/home/git/blog.git checkout -f

6.2 502 Bad Gateway

现象:网站目录有文件,但访问时返回502。

原因:Nginx配置了反向代理(proxy_pass),但没有对应的后端服务。

解决方案:删除所有自定义Nginx配置,使用官方默认配置。bash

1
docker-compose down

修改docker-compose.yml,移除所有配置文件挂载# 修改docker-compose.yml,移除所有配置文件挂载

1
docker-compose up -d

6.3 端口映射后无法访问

原因

  • VPS防火墙未放行映射端口(如88)。

  • 容器端口映射错误(如88:80表示宿主机88映射到容器80,而非反过来)。

解决方案:bash

检查防火墙(Ubuntu示例)

sudo ufw allow 88/tcp

查看容器端口映射

查看容器端口映射

docker port hexo-nginx


7. 日常更新流程

每次写完新文章或修改主题后,只需一条命令:

bash

hexo generate && hexo deploy

Git钩子会自动更新VPS上的网站目录,Nginx容器无需重启即可立即生效。


8. 结语

至此,一个完全自动化的博客部署系统就搭建完成了。回顾整个流程,核心要点是:

  1. 权限是最大的坑:确保git用户对网站目录有写权限,post-receive钩子有执行权限。

  2. Nginx用默认配置:除非需要自定义路由,否则避免在容器中挂载自定义配置文件。

  3. 善用日志docker logs和手动执行钩子是排查问题的两个最有效工具。

这套方案已经在生产环境稳定运行,希望能帮助大家少走弯路,把更多精力放在内容创作上。如果遇到任何问题,欢迎在评论区交流讨论!