VitePress 文档站部署与维护
当前 wiki 站点使用 VitePress 搭建,采用多阶段 Docker 构建生产环境,通过 Traefik 反向代理对外提供 HTTPS 服务。
架构
写 Markdown 文件
↓
Bun → vitepress build (SSR 预渲染)
↓
node:22-alpine + serve (静态文件服务器)
↓
Traefik Gateway → wiki.zipTako.com (HTTPS)| 层级 | 组件 | 职责 |
|---|---|---|
| 编辑器 | 任意文本编辑器 | 写 .md 文件 |
| 构建器 | Bun + VitePress | 将 markdown 构建为静态 HTML |
| 运行时 | node:22-alpine + serve | 轻量静态文件服务 |
| 网关 | Traefik | SSL 终止、域名路由、访问控制 |
项目结构
bash
~/docker/vitepress/
├── Dockerfile # 多阶段构建(Bun 构建 + Node 运行)
├── docker-compose.yml # Traefik 对接配置
├── package.json # VitePress 依赖
└── docs/
├── .vitepress/
│ ├── config.js # 站点导航、主题配置
│ └── cache/ # VitePress 缓存(可删除)
├── index.md # 首页
├── traefik-setup.md # Traefik 部署文档
└── ... # 你的 Markdown 文件(URL 由文件路径自动生成)Dockerfile
采用多阶段构建——Bun 负责快速安装依赖和构建,Node 运行轻量的静态服务器:
dockerfile
FROM oven/bun:latest AS builder
WORKDIR /app
COPY package.json .
RUN bun install --frozen-lockfile
COPY docs ./docs
RUN bunx vitepress build docs
FROM node:22-alpine
WORKDIR /app
RUN npm install -g serve
COPY --from=builder /app/docs/.vitepress/dist /app/dist
EXPOSE 4173
CMD ["serve", "dist", "-l", "4173"]为什么不用
vitepress dev或vitepress preview?
vitepress dev是开发模式(CSR,不适合生产运行)vp preview在 Bun 下有 ESM 兼容性 Bugserve是最轻量的方案(最终镜像约 70MB)
VitePress 配置
js
// docs/.vitepress/config.js
import { defineConfig } from 'vitepress'
export default defineConfig({
title: "Ziptako's Wiki",
description: '我的知识文档站',
vite: {
server: {
allowedHosts: ['wiki.zipTako.com', 'wiki.ziptako.com', 'localhost']
}
},
themeConfig: {
siteTitle: '📚 Ziptako Wiki',
nav: [
{ text: '首页', link: '/' },
{ text: 'Traefik 部署', link: '/traefik-setup' },
],
sidebar: [
{
text: '运维记录',
items: [
{ text: 'Traefik 部署', link: '/traefik-setup' },
],
},
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/ziptako' },
],
footer: {
message: 'Powered by VitePress + Bun + Hermes Agent',
copyright: '© 2026 Ziptako'
}
}
})
vite.server.allowedHosts必须包含所有入口域名(全小写),否则 Vite 会拦截请求。
部署
首次部署
bash
cd ~/docker/vitepress
# 创建 docs 目录
mkdir -p docs/.vitepress/public
# 构建并启动
sudo docker compose up -d --build
# 查看日志确认启动成功
sudo docker compose logs vitepress
# 访问 https://wiki.zipTako.com/正常启动(已有镜像)
bash
cd ~/docker/vitepress
sudo docker compose up -d维护
📝 更新文档内容
修改 ~/docker/vitepress/docs/ 下的 .md 文件后,需要重新构建才能生效:
bash
cd ~/docker/vitepress
# 重新构建镜像(Bun 会缓存 node_modules,构建很快)
sudo docker compose up -d --build
# 确认新容器正常运行
sudo docker compose ps当前是生产模式(静态文件),每次改内容都需要
--build。如果开发阶段想实时预览,请参考下文"切换到 Dev Mode"。
📦 更新 VitePress 版本
bash
cd ~/docker/vitepress
# 编辑 package.json,更新版本号
# "vitepress": "^1.6.0" → "^1.7.0"
# 重新构建(Bun 会下载新版)
sudo docker compose up -d --build
# 验证新版本
sudo docker compose logs vitepress | grep -i vitepress🧹 清理缓存
bash
cd ~/docker/vitepress
sudo rm -rf docs/.vitepress/cache
.vitepress/cache/是 VitePress 的构建缓存,删掉后下次 build 会自动重新生成。
💾 备份
bash
# 只需备份 docs/ 目录中的内容(源码),构建产物可以随时重建
tar czf ~/wiki-backup-$(date +%Y%m%d).tar.gz \
-C ~/docker/vitepress \
Dockerfile docker-compose.yml package.json docs/
# 如果想连同镜像一起备份
sudo docker save vitepress-vitepress:latest -o ~/vitepress-image.tar🔄 重建整个站点
bash
cd ~/docker/vitepress
# 停止并删除容器
sudo docker compose down
# 清理旧镜像
sudo docker rmi vitepress-vitepress:latest 2>/dev/null; sudo docker image prune -f
# 重新构建
sudo docker compose up -d --build
# 验证
sudo docker compose ps🩺 健康检查
bash
# 容器状态
sudo docker ps --filter name=vitepress --format "{{.Names}} {{.Status}}"
# 直接访问容器内的服务
curl -s -H "Host: wiki.zipTako.com" http://localhost:443 | head -5
# 通过 Traefik 访问
curl -sk https://wiki.zipTako.com/ | head -5
# 应返回 HTML(SSR 预渲染,内容直接包含在 HTML 中)
# 查看日志
sudo docker compose logs vitepress --tail 20切换到 Dev Mode(写作模式)
写文章时可以用 Dev Mode,每次保存 .md 文件后浏览器自动刷新,非常适合频繁编辑的场景。
docker-compose.yml(Dev 版)
yaml
services:
vitepress:
build: .
container_name: vitepress
restart: unless-stopped
networks:
- traefik
volumes:
- ./docs:/app/docs
labels:
- "traefik.enable=true"
- "traefik.http.routers.vitepress.rule=Host(`wiki.zipTako.com`)"
- "traefik.http.routers.vitepress.tls=true"
- "traefik.http.routers.vitepress.tls.certresolver=letsencrypt"
- "traefik.http.services.vitepress.loadbalancer.server.port=5173"Dockerfile(Dev 版)
dockerfile
FROM oven/bun:latest AS builder
WORKDIR /app
COPY package.json .
RUN bun install --frozen-lockfile
FROM oven/bun:latest
WORKDIR /app
COPY --from=builder /app/node_modules /app/node_modules
COPY package.json /app/
EXPOSE 5173
CMD ["bunx", "vitepress", "dev", "docs", "--host", "0.0.0.0", "--port", "5173"]Dev ↔ Prod 切换流程
bash
# Dev Mode(写作)
# 1. 编辑 docker-compose.yml:port 改为 5173
# 2. 编辑 Dockerfile:替换为 Dev 版
# 3. 启动
sudo docker compose up -d --build
# 写完后回到生产模式
# 1. 编辑 docker-compose.yml:port 改回 4173
# 2. 编辑 Dockerfile:替换回生产版(多阶段构建)
# 3. 重新构建
sudo docker compose up -d --build⚠️ 不要在生产环境跑 Dev Mode:Vite 开发服务器长期运行可能内存泄漏、暴露 HMR WebSocket 路径、且无法接入 CDN 加速。
常见问题
❌ 修改内容后页面没变
原因:当前是生产模式(静态文件),修改 .md 后需要 --build 重新构建镜像。
解决:sudo docker compose up -d --build
❌ "This host is not allowed"(Dev Mode)
原因:Vite 拦截了来自未知 Host 的连接。
解决:在 config.js 的 vite.server.allowedHosts 中添加域名(全小写),重启容器。
❌ 构建失败
bash
# 查看详细错误
sudo docker compose logs vitepress
# 本地调试构建
cd ~/docker/vitepress
sudo docker build -t vitepress-test .常见原因:
package.json语法错误.md文件中有 VitePress 不支持的语法config.js导入错误
❌ 容器一直重启
bash
# 查看容器状态
sudo docker compose ps
# 查看完整日志
sudo docker compose logs --tail=50 vitepress可能是:
serve启动失败(端口被占用)vitepress build阶段报错但 exit code 仍为 0(检查构建日志)- 内存不足(极罕见,生产模式很轻量)
URL 路由规则
VitePress 根据 docs/ 下的文件路径自动生成路由:
| 文件路径 | 对应 URL |
|---|---|
docs/index.md | / |
docs/traefik-setup.md | /traefik-setup.html |
docs/vitepress-deployment.md | /vitepress-deployment.html |
docs/guide/advanced.md | /guide/advanced.html |
技术选型总结
| 选型 | 原因 |
|---|---|
| VitePress | 基于 Vite,开发体验好,SSR 预渲染,SEO 友好 |
| Bun | 构建阶段用 Bun,bun install 超快(~12s vs npm ~60s) |
| node:22-alpine | 运行时用标准 Node,避免 Bun 的 ESM Bug |
| serve | 最轻量的静态文件服务器,镜像仅 ~70MB |
| Traefik | DNS 服务发现 + 自动 SSL,无需手动配置 Nginx |