Docker容器化基于Nginx的双层反向代理与静态资源服务架构

直接让 Hexo 的开发服务器监听 80 端口虽然简单,但从安全性和功能性的角度看,存在一些不足。本方案通过构建由边缘Nginx至内部Nginx容器的双层反向代理链路,实现了请求的精细化路由与静态资源的高性能服务。

为什么反向代理更安全、更好?

  1. 隐藏真实服务(提升安全)
    • 现状:你现在是让 Hexo 服务器直接对外网(0.0.0.0:80)服务。这意味着用户和潜在的攻击者直接访问的是你的应用(Hexo)。如果 Hexo 本身或某个插件存在未公开的安全漏洞,风险较高。
    • 反向代理:使用反向代理后,用户访问的是 Nginx(反向代理服务器)。Nginx 是一个久经考验、非常稳定和安全的专业 Web 服务器。它作为一道“防护墙”,接收所有外部请求,过滤掉恶意流量后,再转发给内部真正的 Hexo 服务器。攻击者无法直接接触到 Hexo,从而提升了安全性。
  2. 性能提升和负载均衡
    • Hexo 是一个静态站点生成器,其自带的 hexo server是一个轻量级的开发服务器,不适合在高并发环境下生产使用
    • Nginx 是高性能的专业服务器,在处理静态文件(HTML, CSS, JS, 图片)方面效率极高,能显著提升网站的访问速度和并发承受能力。
  3. 功能强大(便于扩展)
    • 通过反向代理,你可以轻松实现很多高级功能,例如:
      • SSL/TLS 终止:在 Nginx 上配置 HTTPS(SSL 证书),让 Nginx 来处理复杂的加密解密工作,减轻内部服务的压力。你面板上的 SSL 功能就是给 Nginx 用的。
      • 缓存:Nginx 可以缓存生成的静态页面,下次访问时直接返回,速度极快。
      • 压缩:Nginx 可以自动压缩文件(Gzip),减少传输体积。
      • 未来扩展:如果你以后需要增加其他服务(如另一个博客、API 接口),可以通过 Nginx 根据不同的域名或路径反向代理到不同的内部服务。

如何为现有的站点配置反向代理?

整个配置流程清晰简单,如下图所示:

第1步:修改 Hexo 容器的配置首先,我们需要让 Hexo 服务在容器的内部端口上运行,而不是直接占用宿主机的 80 端口。

  1. 进入你的 Hexo 容器。docker exec -it leepoet-hexo- /bin/bash
  2. 停止当前可能运行在 80 端口的 Hexo 服务(按 Ctrl+C)。
  3. 让 Hexo 在容器的 4000 端口上运行(这个端口可以任选,只要不冲突即可)。
cd /app
hexo server -i 0.0.0.0 -p 4000   #或其它未被站用的端口

关键点:现在 Hexo 只监听容器内部的 8080端口。外网无法直接访问它。

第2步:在宝塔面板中设置反向代理现在,我们来配置 Nginx,让它将对外部域名(如 leepoet.com)的请求,转发给容器内的 Hexo 服务。

  1. 在你的宝塔面板中,进入对应站点的设置界面。
  2. 点击左侧菜单的 【反向代理】
  3. 点击 【添加反向代理】
  4. 在设置页面中填写:

查看一下DOCKER容器里HEXO的内部IP

  • 代理名称:填写一个易于识别的名字,例如 hexo_blog
  • 目标URL:这是最关键的一步。你需要填写你 Docker 容器的内部 IP 地址和端口
    • 如何查看容器的 IP?在宿主机上执行:
docker inspect leepoet-hexo | grep IPAddress

配置完成后,现在当用户访问 leepoet.com-> 宝塔的Nginx(监听80端口)-> 匹配到创建的反向代理规则​ -> Nginx将请求转发至 http://172.x.x.2:4000-> Docker容器内的Hexo服务器处理请求并返回页面 -> Nginx将页面返回给用户。

*但这个方案并不是很完美。由于Node.js服务与反向代理的双重限制在Node.js容器中运行 hexo server(默认端口4000),而Hexo的开发服务器(hexo server)是轻量级工具,不支持自定义404错误页面,当访问不存在的路径时,会直接返回Node.js内置的“Cannot GET /xxx”错误。宝塔面板设置的反向代理(www.leepoet.com → 172.2.x.x:4000)仅做了简单的流量转发,未对后端返回的404状态码进行拦截和自定义处理,导致错误直接暴露给用户。

延伸的解决方案:用Nginx容器处理静态文件与404错误

架构调整思路

放弃“Node.js容器运行hexo server”的方式,改为:

  1. 生成静态文件:在Node.js容器中通过 hexo generate 生成静态HTML(输出到 /app/public,即宿主机 www/wwwroot/leepoet/public)。
  2. Nginx容器提供服务:新增Nginx容器,挂载静态文件目录并配置404规则,再通过宝塔反向代理到Nginx容器。

具体步骤 部署Nginx容器并挂载静态文件

通过宝塔的Docker管理器或命令行创建Nginx容器:

docker run -d \
  --name leepoet-nginx \
  -p 18181:80 \
  -v /www/wwwroot/leepoet/public:/usr/share/nginx/html:ro \
  nginx:latest

关键参数说明

参数作用
-d后台运行容器
–name leepoet-nginx为容器命名(自定义,便于后续管理,如 docker stop leepoet-nginx)
-p 18181:80端口映射:宿主机端口 18181 → 容器内 Nginx 默认端口 80
-v /www/…:ro挂载静态文件:将宿主机的 Hexo 生成目录(public)挂载到容器内 Nginx 的网页根目录,ro 表示只读权限(安全推荐)
nginx:latest使用最新版 Nginx 镜像(确保本地已拉取,若未拉取会自动下载)
  • 验证Nginx容器是否正常:访问 宿主机IP:18181,应能看到你的博客首页。

修改反向代理为服务器外部IP+18181端口发送域名到www.leepoet.com

配置Nginx容器的404规则
  • 编辑Nginx配置文件 /etc/nginx/conf.d/default.conf,添加404处理:
server {
    listen 80;
    listen [::]:80;
    server_name localhost;  # 若绑定域名,替换为实际域名(如 example.com)

    # 网站根目录:指向 Hexo 生成的 public 文件夹
    root /usr/share/nginx/html;  # 确认此路径下有 Hexo 生成的 public 文件(包括 404.html)
    index index.html index.htm;

    # 关键:将 404 错误指向自定义页面
    error_page 404 /404.html;

    # 核心:支持 Hexo 的路由规则(解决 /about、/category 等路径 404 问题)
    location / {
        try_files $uri $uri/ /index.html;  # 优先加载静态文件,否则交给 Hexo 路由处理
    }

    # 防止直接访问 /404.html 返回 200 状态码(可选但推荐)
    location = /404.html {
        internal;
    }

    # 原有 50x 错误配置(保留)
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

保存,退出并重启DOECKER的NGINX容器

这个时候再进入HEXO的容器里,HEXO CL清理缓存,他会提示一个Hexo 运行时出现 EPERM: operation not permitted, unlink ‘/app/public/.user.ini’ 错误,核心原因是 当前用户对 /app/public 目录或 .user.ini 文件没有写入/删除权限

这个时候只要把这个文件删除,再从回收站还原回来,再继续进HEXO的容器里,执行HEXO CL清理缓存,然后hexo g再hexo s

解决:

两次代理的层次关系:用户请求 → 宝塔Nginx(80端口) → (第一次代理) → Nginx容器(18181端口) → (第二次代理,内部处理) → 静态文件服务

  • “边缘Nginx”:指直接面向公网、运行在宝塔面板中的Nginx(监听80/443端口),它是流量的第一入口,负责SSL终止和初步转发。
  • “内部Nginx容器”:Docker的Nginx容器,负责托管Hexo生成的静态文件。
  • “双层反向代理链路”:精准地描述了“两次代理”的层次关系。
  • “精细化路由”:内部Nginx,如自定义404错误页、路由重写等。
  • “静态资源的高性能服务”:利用Nginx在处理静态文件上的极致性能来替代Hexo的开发服务器。

后续操作:

在每次上传新的md文件和图片到/source的图片及_posts文件夹下后,可以写个脚本执行以下命令

docker restart leepoet-hexo              #重启hexo容器
docker exec -it leepoet-hexo /bin/bash   #进入Hexo容器
cd app                                   #进入app目录
hexo cl                                  #清理hexo缓存
hexo g                                   #hexo生成
hexo s                                   #启动hexo服务
exit                                     #退出DOCKER容器
docker restart leepoet-nginx             #重启nginx容器

至于HEXO篇基本搞定,剩下的THEME类的一般都直接看作者的文档去使用即可。主流的THEME文档作者的README都写的很详细。


往期有关HEXO教程:

LeePoet实操快速上手:Hexo静态博客搭建全攻略

为Hexo博客铺路:Windows匠心配置NodeJS环境的安装

告别环境冲突:在Docker中轻松构建可移植的Hexo博客