Hexo功能强大,主题丰富,可以设计成一个学习经验笔记存档的展馆,结合Docker和Nginx,Hexo还可以作为项目学习、验证与部署过程中的总入口。

一、云服务器的选择于使用

基于性价比最终选择了火山引擎的超小型服务器,使用的是Ubuntu24.04系统,需要配置防火墙打开80和445端口。

二、服务器初始化和安装软件

1. SSH 登录服务器

1
2
ssh root@101.126.131.181
# 输入 root 密码(云平台控制台可重置)

2. 创建普通用户(安全最佳实践)

1
2
3
4
adduser deploy  # 按提示设置密码(建议用字母+数字组合)
usermod -aG sudo deploy # 赋予 sudo 权限
exit # 退出 root
ssh deploy@101.126.131.181 # 用新用户登录

3. 基础安全加固

1
2
3
4
5
6
sudo apt update && sudo apt upgrade -y  # 更新系统
sudo ufw allow OpenSSH # 开放 SSH 端口
# 安装必要软件
sudo apt install nginx git -y # Nginx(Web 服务器) + Git
sudo ufw allow 'Nginx Full' # 开放 Web 端口(HTTP/HTTPS)
sudo ufw enable # 启用防火墙

三、Hexo的安装与配置

第一阶段:Hexo 基础环境与主题安装

首先,我们需要搭建一个基础的博客骨架。

1. 初始化 Hexo
在本地开发机上:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装 Hexo CLI
npm install -g hexo-cli

# 初始化项目
hexo init my-tech-portal
cd my-tech-portal
npm install

# 安装必要的渲染器(Butterfly 主题需要)
npm install hexo-renderer-pug hexo-renderer-stylus --save

# 安装必要插件
npm install hexo-asset-img --save

2. 安装 Theme Butterfly

1
npm install hexo-theme-butterfly --save

3. 启用主题
修改根目录下的 _config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
# _config.yml
# 设置中文语言(可选)
language: zh-CN

# 启用Butterfly主题
theme: butterfly

# 修改 post_asset_folder 为 true 从而便于在 markdown 中添加图片资源
post_asset_folder: true

# 并在底部添加以下内容,用于后续覆盖主题配置而不修改源码
theme_config:
extends:

第二阶段:内容架构改造(实现“双入口”)

我们需要将网站分为两个核心部分:“技术博客”“项目实验室”

1. 创建“项目实验室”页面

这是本方案的核心。我们不使用普通的文章页,而是创建一个独立的展示页。

执行命令:

1
hexo new page projects

2. 编写项目展示页代码 (source/projects/index.md)

我们将在这个文件中直接嵌入 HTML 和 CSS,打造一个类似 Apple App Store 或 Google Play 的卡片式入口。

请将 source/projects/index.md 的内容完全替换为以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
---
title: 项目实验室
date: 2023-10-27 12:00:00
type: "projects"
layout: page
comments: false
---

<style>
/* 注入自定义 CSS - 风格融合:Apple 磨砂 + X 黑白极简 + Google 卡片 */
.project-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
padding: 2rem 0;
}

.project-card {
background: rgba(255, 255, 255, 0.05); /* Apple 风格微透明 */
backdrop-filter: blur(10px);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 20px;
padding: 25px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.02);
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
overflow: hidden;
}

/* 深色模式适配 */
[data-theme="dark"] .project-card {
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.1);
}

.project-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
border-color: #007AFF; /* Apple Blue */
}

.project-status {
position: absolute;
top: 15px;
right: 15px;
font-size: 0.75rem;
padding: 4px 10px;
border-radius: 12px;
font-weight: 600;
letter-spacing: 0.5px;
}

.status-live { background: rgba(52, 199, 89, 0.2); color: #34C759; } /* Green */
.status-dev { background: rgba(255, 149, 0, 0.2); color: #FF9500; } /* Orange */

.project-icon {
width: 50px;
height: 50px;
background: #000;
color: #fff;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin-bottom: 15px;
}

[data-theme="dark"] .project-icon { background: #fff; color: #000; }

.project-title {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 10px;
color: var(--font-color);
}

.project-desc {
font-size: 0.95rem;
color: var(--text-highlight-color);
line-height: 1.6;
margin-bottom: 20px;
opacity: 0.8;
}

.tech-stack {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 20px;
}

.tech-tag {
font-size: 0.75rem;
padding: 3px 8px;
border-radius: 6px;
background: rgba(0,0,0,0.05);
color: var(--font-color);
border: 1px solid rgba(0,0,0,0.05);
}
[data-theme="dark"] .tech-tag { background: rgba(255,255,255,0.1); border-color: rgba(255,255,255,0.1); }

.project-link {
display: inline-flex;
align-items: center;
justify-content: center;
width: 100%;
padding: 12px 0;
background: #000;
color: #fff !important;
border-radius: 12px;
font-weight: 600;
text-decoration: none !important;
transition: opacity 0.2s;
}

[data-theme="dark"] .project-link { background: #fff; color: #000 !important; }
.project-link:hover { opacity: 0.8; }

</style>

<div class="project-container">

<div class="project-card">
<div class="project-status status-live">运行中</div>
<div class="project-icon"><i class="fas fa-robot"></i></div>
<h3 class="project-title">AI Chatbot Assistant</h3>
<p class="project-desc">基于 LLM 的对话机器人前端验证,采用 Streamlit 构建,通过 Docker 容器化部署。</p>
<div class="tech-stack">
<span class="tech-tag">Python</span>
<span class="tech-tag">Docker</span>
<span class="tech-tag">Streamlit</span>
</div>
<a href="/demos/chatbot/" class="project-link" target="_blank">进入应用 <i class="fas fa-arrow-right" style="margin-left:8px"></i></a>
</div>

<div class="project-card">
<div class="project-status status-dev">开发中</div>
<div class="project-icon"><i class="fas fa-chart-line"></i></div>
<h3 class="project-title">Data Viz Dashboard</h3>
<p class="project-desc">Vue3 + ECharts 构建的数据可视化大屏,用于展示服务器实时监控数据。</p>
<div class="tech-stack">
<span class="tech-tag">Vue3</span>
<span class="tech-tag">Nginx</span>
</div>
<a href="/demos/dashboard/" class="project-link" target="_blank">查看演示</a>
</div>

</div>

第三阶段:UI/UX 设计定制(Global Config)

为了达到“简约高效”的效果,我们需要配置 _config.butterfly.yml(在根目录新建此文件以覆盖默认主题配置)。

创建/修改 _config.butterfly.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 导航菜单:清晰区分“文章”和“项目”
menu:
首页: / || fas fa-home
项目实验室: /projects/ || fas fa-flask
学习笔记: /archives/ || fas fa-book-open
# 关于我: /about/ || fas fa-user

# 副标题
subtitle:
enable: true
effect: true # 开启打字机效果
# 如果想用自己写的文字:
source: false
sub:
- 既然选择了远方,便只顾风雨兼程
- 夜色难免黑凉、前行必有曙光

# 更换头像(Avatar)
avatar:
img: /img/your_avatar.jpg # 这里的路径对应 source/img/your_avatar.jpg
effect: true # 是否开启旋转效果

# 侧边栏
aside:
card_author:
button:
enable: false # follow me 按钮
card_announcement: # 公告内容
enable: true
content: 本网站为个人技术验证与展示平台,主要用于记录本人在软件开发领域的学习心得,以及项目的实践、验证与展示。网站内容均为原创,非商业性用途,旨在进行经验与作品展示,便于同行交流,共同进步。

# 社交属性 这通常指的是侧边栏个人卡片下方的图标。
social:
fab fa-github: https://github.com/你的用户名 || Github # || "#191717"
fas fa-envelope: mailto:你的邮箱 || Email # || "#000000"
# 格式:图标类名: 链接 || 悬停提示文字 || 颜色(不设置颜色则由主题自动适配暗色和浅色模式)图标类名可以在 Font Awesome 网站找到。

# 视觉风格设定
index_img: /img/home-bg.jpg # 找一张极简的高科技感背景图

# 所有页面的默认顶图(如果文章没有单独设置 cover)
default_top_img: /img/default.jpg

# 设置全局背景,可以是图片 URL 或 CSS 颜色代码
background: url(/img/bg.jpg)
# 或者纯色
# background: "#f0f0f0"

# 启用黑夜模式切换 (X 风格)
darkmode:
enable: true
button: true
autochange: true

# 字体设置 (Apple 风格)
font:
global-font-size: 16px
code-font-size: 14px
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft YaHei", sans-serif

# 底部精简
footer:
owner:
enable: true
since: 2024
custom_text: "Powered by <a href='https://hexo.io'>Hexo</a> | Deployed via <a href='https://www.docker.com'>Docker</a>"

# 代码块风格 (Mac 风格红黄绿点)
highlight_theme: mac

这些页面默认是不存在的,需要你手动创建。

**步骤 1:**创建文件 在终端(Terminal)运行以下命令:

1
2
hexo new page tags
hexo new page categories

**步骤 2:**配置 Front-matter 找到你刚刚生成的 source/tags/index.md 文件,修改内容为:

1
2
3
4
5
6
---
title: 标签
date: 2023-10-27 10:00:00
type: "tags" # 这一行最重要,告诉主题这是标签页
comments: false
---

同样的,修改 source/categories/index.md

1
2
3
4
5
6
---
title: 分类
date: 2023-10-27 10:00:00
type: "categories" # 这一行最重要
comments: false
---

**步骤 3:**如果想同时在菜单中启用 最后确保在 _config.butterfly.yml menu: 中取消了相关注释:

1
2
3
4
menu:
首页: / || fas fa-home
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open

为了帮助你更好地理解如何创建 Tags 和 Categories 页面,推荐观看以下视频:

[Tags & Categories | Hexo Tutorial][https://www.youtube.com/watch?v=UNTk5XkXKdQ]

这个视频详细演示了如何在 Hexo 中手动创建标签和分类页面,正好解决了你提到的“点开是空的”问题。


第四阶段:部署 Hexo 静态页面

💡 核心思路:将本地 hexo generate 生成的 public 目录文件上传到服务器

1. 本地生成静态文件(在你自己的电脑操作)

1
2
cd 你的hexo项目目录
hexo clean && hexo generate # 生成最新静态文件
  • 生成的文件位于 项目目录/public

2. 上传文件到服务器(任选一种方式)

方式 A:SCP 上传(推荐,简单直接)

1
scp -r public/* deploy@101.126.131.181:/tmp/hexo_site

方式 B:Git 上传(适合长期维护)

  • 本地:将 public 目录推送到 GitHub/Gitee 仓库

  • 服务器:

    1
    2
    3
    4
    5
    6
    sudo mkdir -p /var/www/hexo
    sudo chown -R deploy:deploy /var/www/hexo # 授权
    cd /var/www/hexo
    git init
    git remote add origin https://gitee.com/wquan0717/hexo-garden.git
    git pull origin master # 或 main

3. 配置 Nginx 服务

1
sudo nano /etc/nginx/sites-available/hexo.conf

粘贴以下配置(替换 your_domain_or_ip 为你的域名或服务器 IP):

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
listen [::]:80;
server_name 101.126.131.181; # 例如 123.123.123.123 或 example.com

root /var/www/hexo; # 静态文件目录
index index.html;

location / {
try_files $uri $uri/ =404;
}
}

启用配置:

1
2
sudo ln -s /etc/nginx/sites-available/hexo.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx # 测试并重载

4. 移动文件到 Web 目录

1
2
3
4
5
6
7
8
# 若用 SCP 上传:
sudo mv /tmp/hexo_site/* /var/www/hexo/

# 若用 Git 上传(已在 /var/www/hexo):
# 跳过此步

# 设置权限
sudo chown -R www-www-data /var/www/hexo # Nginx 默认用户

第五阶段:验证部署

  1. 浏览器访问 http://101.126.131.181
  2. 看到 Hexo 默认页面即成功!

第六阶段、后续优化建议

  1. 绑定域名(可选):

    • 在云平台控制台将域名 DNS 解析到服务器 IP
    • 修改 Nginx 配置中的 server_name 为你的域名
  2. 启用 HTTPS(免费证书):

    1
    2
    sudo apt install certbot python3-certbot-nginx -y
    sudo certbot --nginx -d wquan0717.top # wquan0717.top为域名
  3. 自动化部署(进阶):

    • 用 GitHub Actions + SSH 自动上传文件
    • 或配置 Webhook 监听 Git 仓库更新

四、Docker的安装与配置

采用离线安装 Docker:本地下载 + 服务器上传方案

第一步:在本地电脑准备安装包(关键步骤)

1. 确认服务器系统架构

1
2
# 在服务器执行(确认架构)
uname -m

常见结果:

  • x86_64 → 选择 AMD64 包
  • aarch64 → 选择 ARM64 包(如果是 ARM 服务器)

2. 本地下载 Docker 安装包(在你的电脑操作)

选项 A:直接下载官方 DEB 包(推荐)

访问官方下载页面:
👉 [https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/][]

根据你的架构下载以下 5 个文件(示例为 AMD64):

1
2
3
4
5
6
7
8
9
10
# 容器运行时
containerd.io_1.6.32-1_amd64.deb

# Docker 核心组件
docker-ce_25.0.3-1~ubuntu.22.04~jammy_amd64.deb
docker-ce-cli_25.0.3-1~ubuntu.22.04~jammy_amd64.deb

# 扩展工具
docker-buildx-plugin_0.12.1-1~ubuntu.22.04~jammy_amd64.deb
docker-compose-plugin_2.24.5-1~ubuntu.22.04~jammy_amd64.deb
选项 B:使用 Docker 官方脚本生成离线包(高级)
1
2
3
4
# 在本地 Ubuntu 虚拟机执行(非必须)
wget https://get.docker.com -O get-docker.sh
bash get-docker.sh --dry-run > docker-packages.txt
apt download $(cat docker-packages.txt)

3. 创建安装包集合

1
2
mkdir docker-offline
# 将下载的 5 个 .deb 文件放入此目录

第二步:上传到服务器

1
2
# 在本地电脑操作(替换为你的实际路径和IP)
scp -r ./docker-offline deploy@101.126.131.181:/tmp/

第三步:在服务器上离线安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 进入安装包目录
cd /tmp/docker-offline

# 2. 按依赖顺序安装(关键!)
sudo dpkg -i containerd.io_*.deb
sudo dpkg -i docker-ce-cli_*.deb
sudo dpkg -i docker-ce_*.deb
sudo dpkg -i docker-buildx-plugin_*.deb
sudo dpkg -i docker-compose-plugin_*.deb

# 3. 修复可能的依赖问题
sudo apt --fix-broken install -y

# 4. 启动服务并设置开机自启
sudo systemctl enable --now docker
sudo systemctl start docker

# 5. 验证安装
sudo docker --version
# 应显示 Docker version 25.0.3, build 4c7a1fa

# 6. 安装增强工具
sudo apt install -y htop net-tools

第四步:永久授权用户(避免 sudo)

1
2
3
4
5
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER

# 刷新组权限(立即生效)
newgrp docker

第五步:离线镜像准备

1
2
3
4
5
6
7
8
9
10
# 在本地下载常用镜像
docker pull nginx:alpine
docker pull nginxproxy/nginx-proxy:alpine
docker save -o nginx-images.tar nginx:alpine nginxproxy/nginx-proxy:alpine

# 上传到服务器
scp nginx-images.tar deploy@101.126.131.181:/tmp/

# 服务器加载
docker load -i /tmp/nginx-images.tar

第六步:于本地构建项目为Docker镜像,上传到服务器使用

第一步:安装 Docker 环境

我们需要安装 Docker Engine (负责运行容器) 和 Docker Compose (负责管理多容器配置,工程化必备)。

1. 一键安装 Docker (适用于 Ubuntu/Debian/CentOS)
这是官方提供的最快安装脚本:

1
2
# 下载并执行官方安装脚本
curl -fsSL https://get.docker.com | bash

2. 启动并设置开机自启

1
2
# sudo systemctl start docker #可选
sudo systemctl enable docker

3. 配置权限 (重要)
默认情况下 Docker 需要 sudo 才能执行。为了方便后续操作,把当前用户加入 docker 用户组:

1
2
3
4
5
6
7
8
# 将当前用户加入 docker 组
sudo usermod -aG docker $USER

# 刷新用户组(或者直接退出服务器重新 SSH 登录)
newgrp docker

# 验证安装是否成功
docker version

第二步:规划项目目录结构

为了保持服务器整洁,不要把文件乱放。建议在用户主目录下建立一个 appsprojects 目录。

1
2
3
4
5
6
7
8
# 创建项目总目录
mkdir -p ~/projects

# 创建我们将要演示的第一个项目目录:demo-chatbot
mkdir -p ~/projects/demo-chatbot

# 进入目录
cd ~/projects/demo-chatbot

第三步:编写项目代码 (Docker 里的内容)

我们模拟一个简单的动态网站(比如一个 Python Flask 接口),这将验证你的 Nginx 转发是否成功。

你需要创建以下 3 个文件。你可以使用 vimnano 创建它们。

1
cd ~/projects/demo-chatbot
1. app.py (业务代码)

这是一个极简的 Web 服务,它会返回当前的服务器时间和一条欢迎信息。

1
sudo nano app.py

复制粘贴以下内容,按 Ctrl+s 保存,按 Ctrl+x 退出编辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 文件名: app.py
from flask import Flask
import datetime
import socket

app = Flask(__name__)

@app.route('/')
def hello():
hostname = socket.gethostname()
time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# 这里模拟一个带有现代感的返回界面
html = f"""
<div style="font-family: sans-serif; text-align: center; padding: 50px;">
<h1 style="color: #333;">🚀 Docker 部署成功</h1>
<p>这是一个运行在 Docker 容器内的 Python 应用。</p>
<p><strong>容器 ID:</strong> {hostname}</p>
<p><strong>当前时间:</strong> {time_str}</p>
</div>
"""
return html

if __name__ == '__main__':
# 监听 0.0.0.0 才能让外部(Docker 宿主机)访问
app.run(host='0.0.0.0', port=5000)
2. requirements.txt (依赖清单)

告诉 Docker 需要安装什么 Python 包。

1
sudo nano requirements.txt

复制粘贴以下内容,按 Ctrl+s 保存,按 Ctrl+x 退出编辑。

1
2
# 文件名: requirements.txt
Flask==3.0.0
3. Dockerfile (构建说明书)

这是告诉 Docker 如何把上面的代码打包成一个镜像。

1
sudo nano Dockerfile

复制粘贴以下内容,按 Ctrl+s 保存,按 Ctrl+x 退出编辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 文件名: Dockerfile

# 1. 使用官方 Python 轻量级基础镜像
FROM python:3.9-slim

# 2. 设置工作目录
WORKDIR /app

# 3. 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 4. 复制项目代码
COPY app.py .

# 5. 暴露容器内部端口
EXPOSE 5000

# 6. 启动命令
CMD ["python", "app.py"]

第四步:使用 Docker Compose 管理 (核心步骤)

不要直接使用 docker run 命令,那是新手的做法。使用 docker-compose.yml 可以让你把配置写在文件里,方便以后维护。

进入 ~/projects/demo-chatbot/ 目录:

1
cd ~/projects/demo-chatbot

~/projects/demo-chatbot/ 目录下创建 docker-compose.yml

1
sudo nano docker-compose.yml

复制粘贴以下内容,按 Ctrl+s 保存,按 Ctrl+x 退出编辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 文件名: docker-compose.yml
version: '3.8'

services:
# 服务名称
chatbot:
# 告诉 Docker 在当前目录寻找 Dockerfile 构建镜像
build: .
# 容器名称,方便查看日志
container_name: my-chatbot-container
# 总是自动重启(防止程序崩溃或服务器重启后挂掉)
restart: always
# 端口映射: 左边是服务器端口(8081),右边是容器端口(5000)
# 我们只监听 127.0.0.1,这样只有本机的 Nginx 能访问它,外网无法直接通过 IP:8081 访问,更安全
ports:
- "127.0.0.1:8081:5000"
# 资源限制(可选,防止占满服务器内存)
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M

第五步:启动项目!

现在一切准备就绪,开始运行。

1
2
3
4
5
6
# 确保你在 ~/projects/demo-chatbot 目录下
cd ~/projects/demo-chatbot

# 1. 构建并后台启动
# -d 表示在后台运行 (Detached mode)
docker compose up -d --build

验证是否成功:
运行 docker ps,你应该能看到类似这样的输出:

1
2
CONTAINER ID   IMAGE                 STATUS          PORTS                      NAMES
a1b2c3d4e5f6 demo-chatbot-chatbot Up 10 seconds 127.0.0.1:8081->5000/tcp my-chatbot-container

此时,你的应用已经在本机内部的 127.0.0.1:8081 上跑起来了!

第六步:构建项目Docker镜像

镜像导出/导入法(推荐,最简单可靠)

步骤1:在本地电脑导出 Chatbot 镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1.1 找到你的 chatbot 容器ID或镜像名
docker ps -a
# 示例输出:CONTAINER ID IMAGE ... NAMES
# 9270c19578e1 demo-chatbot ... my-chatbot-container

# 1.2 停止容器(避免数据不一致)
docker stop my-chatbot-container

# 1.3 提交容器为新镜像(可选,如果需要保存运行状态)
docker commit 9270c19578e1 demo-chatbot:latest

# 1.4 导出镜像为tar文件
docker save -o demo-chatbot.tar demo-chatbot:latest

# 1.5 验证文件大小(通常50-500MB)
ls -lh demo-chatbot.tar
步骤2:上传到服务器
1
2
# 在本地电脑执行
scp demo-chatbot.tar deploy@101.126.131.181:/tmp/
步骤3:在服务器导入并运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3.1 导入镜像
docker load -i /tmp/demo-chatbot.tar

# 3.2 验证镜像存在
docker images
# 应看到 demo-chatbot:latest

# 3.3 创建项目目录
mkdir -p ~/projects/chatbot
cd ~/projects/chatbot

# 3.4 创建 docker-compose.yml
cat > docker-compose.yml <<EOF
version: '3.8'
services:
chatbot:
image: demo-chatbot:latest
container_name: my-chatbot-container
expose:
- "5000" # 仅容器内部暴露,通过代理访问
restart: always
ports:
- "127.0.0.1:8081:5000"
# 资源限制(推荐)
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
EOF

# 3.5 启动服务
docker compose up -d

第七步:配置 Nginx 连接 Docker

现在我们需要修改 Nginx,让它把用户对 /demos/chatbot/ 的访问,转发给 Docker 的 8081 端口。

1. 编辑 Nginx 配置文件
(假设你的配置文件在 /etc/nginx/sites-available/hexo.conf

进入编辑器:

1
sudo nano /etc/nginx/sites-available/hexo.conf

执行以下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
listen 80;
server_name yourdomain.com; # 替换你的域名

# Hexo 静态博客 (保持不变)
location / {
root /var/www/hexo;
index index.html;
# try_files $uri $uri/ /index.html;
try_files $uri $uri/ =404;
}

# ---> 新增:Docker 项目入口 <---
location /demos/chatbot/ {
# 这里的端口必须和 docker-compose.yml 里的宿主机端口一致 (8081)
proxy_pass http://127.0.0.1:8081/;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 解决 Flask 可能出现的路径问题
proxy_redirect off;
}
}

2. 测试并重启 Nginx

1
2
3
4
5
# 测试配置是否有语法错误
sudo nginx -t

# 如果显示 successful,则重启 Nginx
sudo systemctl reload nginx

五、工作流演示

工作流

  1. 发布学习笔记

    • hexo new post "Docker学习心得"
    • 写 Markdown,hexo g,文件部署到 /var/www/hexo
    • 访客通过首页的“学习笔记”查看。
  2. 发布新项目 (例如一个 Go 语言写的 API 服务)

    • Docker 端:编写 Dockerfile,启动容器映射到 8083 端口。
    • Nginx 端:添加 location /demos/go-api/ { proxy_pass http://127.0.0.1:8083/; } 并重载 Nginx。
    • Hexo 端:编辑 source/projects/index.md,复制一个 <div class="project-card"> 块,修改标题、描述,并将链接指向 /demos/go-api/
    • 部署:重新生成 Hexo (hexo g) 并上传。
  3. 如果需要在markdown中添加图片等资源,并使用 Typora 编辑器,可进行如下设置:

    1. 打开Typora的偏好设置

    2. 点击“图像”

    3. 按照如下方式设置和勾选:

      image-20251219162337884

总结

这套方案通过修改 Hexo 的 page 布局,利用 HTML/CSS 手写了一个高度定制化的“应用商店”风格的项目入口页,避开了维护两个独立前端系统的麻烦。同时,利用 Nginx 的 location 块级路由,完美地将静态博客与后端 Docker 容器串联起来。

下一步建议

为了让网站看起来更像“X”或“Apple”的设计,建议你为每个项目准备一个 SVG 图标

增强 Hexo 一键部署

hexo dhexo deploy 命令的简写形式,用于将生成的静态网站文件自动部署到配置的目标位置。

核心功能

  • 作用:将 hexo generate 生成的 public 目录中的文件自动上传/同步到远程服务器或托管平台
  • 前提:必须先执行 hexo generate(或直接使用 hexo g -d 一键生成+部署)
  • 依赖配置:需要在 Hexo 项目的 _config.yml 文件中预先配置部署参数

常见部署类型配置示例

1. Git 部署(GitHub Pages/Gitee Pages)

1
2
3
4
5
deploy:
type: git
repo: git@github.com:username/username.github.io.git
branch: main
message: "Site updated: {{ now }}"

2. rsync 部署(到云服务器,适合你的场景)

1
2
3
4
5
6
7
8
9
deploy:
type: rsync
host: 你的服务器IP
user: deploy
root: /var/www/hexo
port: 22
delete: true
verbose: true
ignore_errors: false

3. FTP 部署

1
2
3
4
5
6
deploy:
type: ftpsync
host: your.server.com
user: username
pass: password
remote_dir: /path/to/www

你的场景中的实用建议

既然你已经在云服务器上配置了 Nginx,推荐使用 rsync 部署方式替代手动上传:

  1. 安装部署插件(在本地 Hexo 项目目录):

    1
    npm install hexo-deployer-rsync -s
  2. 配置 _config.yml

    1
    2
    3
    4
    5
    6
    7
    8
    deploy:
    type: rsync
    host: 101.126.131.181 # 你的服务器IP
    user: deploy
    root: /var/www/hexo
    port: 22
    delete: true
    verbose: true
  3. 一键部署

    1
    2
    3
    4
    5
    hexo clean && hexo g -d
    # 等价于:
    # hexo clean
    # hexo generate
    # hexo deploy

与你当前方式的对比

方式 你的当前方式 hexo d (rsync)
操作步骤 1. 本地生成
2. 手动SCP上传
3. SSH登录设置权限
一条命令完成全部操作
速度 较慢(需人工干预) 极快(自动化)
一致性 可能漏传文件 保证完整同步
适用场景 一次性部署 频繁更新博客

⚠️ 重要提示

  • 首次使用 hexo d 前需安装对应部署插件:npm install hexo-deployer-gitnpm install hexo-deployer-rsync

  • 服务器需配置 SSH 免密登录(更安全便捷):

    1
    2
    # 本地操作
    ssh-copy-id deploy@101.126.131.181
  • 部署后需确保文件权限正确:

    1
    2
    # 在部署配置中添加
    args: "&& sudo chown -R www-data:www-data /var/www/hexo"

💡 建议:在你的场景中,配置 rsync 部署是最优解。只需首次设置,后续写完文章后执行 hexo g -d 即可秒级更新线上博客,无需手动操作服务器。