docs: 部署手册拆分为多页,左侧形成三层目录

原单页塞了 13 个二级标题、右侧目录过长。拆成 7 页:
- 概览(含选型指引与环境对照表)
- 路径前缀必读(独立成页,最高频故障)
- 推荐环境:Docker + nginx
- 静态托管部署(nginx 子路径/根路径、Apache、Caddy、对象存储、pnpm)
- 内网与离线部署(4 种方案 + 对比表)
- 本地开发与预览(含新增页面步骤)
- 常见问题(部署/构建/运行三类 + 自检清单)

侧边栏分为三组:部署手册 / 部署方式 / 开发与排错
This commit is contained in:
Dai0814
2026-10-26 17:12:18 +08:00
parent 07ddaa9968
commit 22a177c569
8 changed files with 860 additions and 389 deletions
+159
View File
@@ -0,0 +1,159 @@
---
title: Docker + nginx 部署
description: 推荐环境部署方式:多阶段构建镜像 + nginx 托管
outline: deep
---
# 推荐环境部署:Docker + nginx
适用:生产环境、需要长期稳定运行、机器上不想装 Node。
仓库自带多阶段 `Dockerfile`:Node 阶段执行 `vitepress build`,最终镜像只含 nginx 与静态产物,**不含 Node 和 `node_modules`**。
## 构建镜像
```bash
SHA=$(git rev-parse --short HEAD)
docker build -t iotlcm-docs:$SHA .
```
用 commit sha 做标签,便于追溯与回滚;不建议只用 `latest`。
## 启动容器
```bash
docker run -d \
--name iotlcm-docs \
--restart unless-stopped \
-p 8019:80 \
iotlcm-docs:$SHA
```
## nginx 配置(关键)
`docker/nginx.conf` 用 `alias` 把 `/docs/` 前缀剥掉:
```nginx
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# 产物按 base=/docs/ 生成,资源引用形如 /docs/assets/xxx
location /docs/ {
alias /usr/share/nginx/html/;
try_files $uri $uri.html $uri/ $uri/index.html =404;
}
# 根路径跳到文档入口,避免访问 / 时白屏
location = / {
return 302 /docs/;
}
location / {
try_files $uri $uri.html $uri/ =404;
}
}
```
`try_files` 里的 `$uri.html` 与 `$uri/index.html` 是必需的:配置启用了 `cleanUrls: true`,页面 URL 不带 `.html` 后缀,需要服务器做内部映射。
原理说明见 [路径前缀必读](./path-prefix)。
## 部署后自检
```bash
# 1. 入口可访问(应返回 200)
curl -o /dev/null -s -w '%{http_code}\n' http://127.0.0.1:8019/docs/
# 2. 根路径应 302 到 /docs/
curl -o /dev/null -s -w '%{http_code}\n' http://127.0.0.1:8019/
# 3. 静态资源不能 404(最容易出问题的一步)
ASSET=$(curl -s http://127.0.0.1:8019/docs/ | grep -o '/docs/assets/style[^"]*\.css' | head -1)
curl -o /dev/null -s -w '%{http_code}\n' "http://127.0.0.1:8019$ASSET"
# 4. 抽查正文页面
curl -o /dev/null -s -w '%{http_code}\n' http://127.0.0.1:8019/docs/manual/web/
```
四项都返回 `200`(第 2 项返回 `302`)才算部署成功。
## 通过外层反向代理对外
生产常见做法:容器只监听 `127.0.0.1`,由外层 nginx 转发。
```nginx
upstream iotlcm_docs {
server 127.0.0.1:8019;
}
location = /docs {
return 301 /docs/;
}
location /docs/ {
proxy_pass http://iotlcm_docs; # 末尾不要加斜杠
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
::: danger proxy_pass 末尾斜杠
写成 `proxy_pass http://iotlcm_docs/;`(带末尾斜杠)会把 `/docs/` 前缀剥掉,转发到容器变成 `/`,导致资源全部 404 白屏。**必须不带末尾斜杠**。
:::
## docker compose
`docker-compose.yml` 中镜像名是占位值,需替换为自己的仓库地址:
```yaml
services:
docs:
image: your-registry/iotlcm/iotlcm-docs:${TAG:-latest}
container_name: iotlcm-docs
restart: unless-stopped
ports:
- "127.0.0.1:8019:80"
networks:
- iotlcm-network
networks:
iotlcm-network:
external: true
name: iotlcm-network
```
compose 文件声明 `iotlcm-network` 为外部网络,若不存在需先创建:
```bash
docker network create iotlcm-network
```
启动:
```bash
TAG=$(git rev-parse --short HEAD) docker compose up -d
```
## 版本固定与升级
开源仓按**固定版本**发布(无 git 历史,单次初始提交)。部署时请记录并锁定 commit:
```bash
SHA=$(git rev-parse HEAD)
echo "部署基线: $SHA" >> deploy.log
docker build -t iotlcm-docs:$SHA .
```
升级文档时,从上游选定基线重新发布后,按新 sha 重建镜像并滚动替换容器:
```bash
docker rm -f iotlcm-docs
docker run -d --name iotlcm-docs --restart unless-stopped -p 8019:80 iotlcm-docs:$NEW_SHA
```