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