Files
YouduWiki/DEPLOY_UBUNTU22.md
2026-05-21 19:53:36 +08:00

774 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PandaWiki Ubuntu 22.04 内网部署指南
本文档涵盖从源码传输、构建 Docker 镜像到部署运行的完整流程。
---
## 一、整体部署架构
```
┌──────────────────────────────────────────────────┐
│ Ubuntu 22.04 Server │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Nginx/Caddy │ │ Admin 前端 │ │
│ │ (反向代理) │ │ (Nginx) │ │
│ │ 端口: 80/443│ │ 端口: 5000 │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ API 服务 (Go) │ 端口: 8000 │
│ │ Consumer 服务 (Go) │ 后台异步任务 │
│ └──────────┬───────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ PG │ │Redis │ │ NATS │ │MinIO │ │
│ │ :5432│ │:6379 │ │:4222 │ │:9000 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ │
│ ┌──────────────────────┐ │
│ │ RAG 向量检索服务 │ 端口: 5050 │
│ └──────────────────────┘ │
│ │
│ ┌──────────────────────┐ │
│ │ AI 大模型 API │ 外部配置 │
│ └──────────────────────┘ │
└──────────────────────────────────────────────────┘
```
---
## 二、服务器环境准备
### 2.1 系统要求
```bash
# 确认系统版本
lsb_release -a
# Ubuntu 22.04.x LTS
# 建议配置
# CPU: 4 核以上
# 内存: 8 GB 以上 (AI 相关功能需要更多)
# 磁盘: 50 GB 以上
```
### 2.2 安装 Docker
```bash
# 卸载旧版本 (如果有)
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装依赖
sudo apt-get update
sudo apt-get install -y \
ca-certificates \
curl \
gnupg \
lsb-release
# 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加 Docker 仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# 验证安装
sudo docker --version
sudo docker compose version
# 将当前用户加入 docker 组 (免 sudo)
sudo usermod -aG docker $USER
newgrp docker
# 设置 Docker 开机自启
sudo systemctl enable docker
```
### 2.3 安装 Docker Compose (独立版,可选)
Docker 新版已内置 `docker compose` 插件。如需独立版:
```bash
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```
### 2.4 安装 Git (用于获取源码)
```bash
sudo apt-get install -y git
```
---
## 三、传输源码到服务器
### 方式 AGit 仓库 (服务器有网络)
```bash
# 在服务器上
git clone https://github.com/chaitin/PandaWiki.git
cd PandaWiki
# 然后将你 Windows 上修改过的文件传输到服务器覆盖对应文件
# 需要覆盖的文件:
# backend/domain/license.go
# backend/usecase/stat.go
# backend/repo/pg/auth.go
# web/admin/src/constant/version.ts
```
### 方式 B直接 SCP 传输整个项目 (推荐)
在 Windows 上使用 PowerShell 或 WSL
```powershell
# 在 Windows 上执行,将整个项目传到服务器
scp -r "E:\code project\PandaWiki-3.85.0" user@your-server-ip:/home/user/
# 或者用 rsync (WSL/Linux)
rsync -avz --progress \
"/mnt/e/code project/PandaWiki-3.85.0/" \
user@your-server-ip:/home/user/PandaWiki/
```
### 方式 C打包传输
```bash
# 在 Windows 上打包 (Git Bash / WSL)
cd "E:\code project\PandaWiki-3.85.0"
tar --exclude='.git' -czf panda-wiki.tar.gz .
# 传输到服务器
scp panda-wiki.tar.gz user@your-server-ip:/home/user/
# 在服务器上解压
mkdir -p ~/PandaWiki && cd ~/PandaWiki
tar -xzf ~/panda-wiki.tar.gz
```
---
## 四、创建 Docker Compose 配置
在项目根目录创建 `docker-compose.yml`
```bash
cd ~/PandaWiki
```
```yaml
# docker-compose.yml
version: '3.8'
services:
# ========== 基础设施 ==========
postgres:
image: postgres:16-alpine
container_name: panda-wiki-postgres
restart: unless-stopped
environment:
POSTGRES_USER: panda-wiki
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe123!}
POSTGRES_DB: panda-wiki
volumes:
- pg_data:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U panda-wiki"]
interval: 5s
timeout: 5s
retries: 5
networks:
- panda-wiki
redis:
image: redis:7-alpine
container_name: panda-wiki-redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-ChangeMe123!}
volumes:
- redis_data:/data
ports:
- "127.0.0.1:6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 5s
timeout: 5s
retries: 5
networks:
- panda-wiki
nats:
image: nats:2-alpine
container_name: panda-wiki-nats
restart: unless-stopped
command: >
-js
-m 8222
--user ${NATS_USER:-panda-wiki}
--pass ${NATS_PASSWORD:-ChangeMe123!}
ports:
- "127.0.0.1:4222:4222"
- "127.0.0.1:8222:8222"
networks:
- panda-wiki
minio:
image: minio/minio:latest
container_name: panda-wiki-minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${S3_ACCESS_KEY:-s3panda-wiki}
MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY:-ChangeMe123!}
volumes:
- minio_data:/data
ports:
- "127.0.0.1:9000:9000"
- "127.0.0.1:9001:9001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 10s
timeout: 5s
retries: 5
networks:
- panda-wiki
# ========== 业务服务 ==========
api:
build:
context: ./backend
dockerfile: Dockerfile.api
image: panda-wiki-api:latest
container_name: panda-wiki-api
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe123!}
NATS_PASSWORD: ${NATS_PASSWORD:-ChangeMe123!}
REDIS_PASSWORD: ${REDIS_PASSWORD:-ChangeMe123!}
JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-me}
S3_SECRET_KEY: ${S3_SECRET_KEY:-ChangeMe123!}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}
LOG_LEVEL: ${LOG_LEVEL:-0}
ENV: ${ENV:-production}
SENTRY_ENABLED: "false"
PG_DSN: "host=panda-wiki-postgres user=panda-wiki password=${POSTGRES_PASSWORD:-ChangeMe123!} dbname=panda-wiki port=5432 sslmode=disable TimeZone=Asia/Shanghai"
MQ_NATS_SERVER: "nats://panda-wiki-nats:4222"
REDIS_ADDR: "panda-wiki-redis:6379"
S3_ENDPOINT: "panda-wiki-minio:9000"
RAG_CT_RAG_BASE_URL: ${RAG_BASE_URL:-http://host.docker.internal:5050}
ports:
- "127.0.0.1:8000:8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nats:
condition: service_started
minio:
condition: service_healthy
networks:
- panda-wiki
consumer:
build:
context: ./backend
dockerfile: Dockerfile.consumer
image: panda-wiki-consumer:latest
container_name: panda-wiki-consumer
restart: unless-stopped
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe123!}
NATS_PASSWORD: ${NATS_PASSWORD:-ChangeMe123!}
REDIS_PASSWORD: ${REDIS_PASSWORD:-ChangeMe123!}
JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-me}
S3_SECRET_KEY: ${S3_SECRET_KEY:-ChangeMe123!}
LOG_LEVEL: ${LOG_LEVEL:-0}
ENV: ${ENV:-production}
SENTRY_ENABLED: "false"
PG_DSN: "host=panda-wiki-postgres user=panda-wiki password=${POSTGRES_PASSWORD:-ChangeMe123!} dbname=panda-wiki port=5432 sslmode=disable TimeZone=Asia/Shanghai"
MQ_NATS_SERVER: "nats://panda-wiki-nats:4222"
REDIS_ADDR: "panda-wiki-redis:6379"
S3_ENDPOINT: "panda-wiki-minio:9000"
RAG_CT_RAG_BASE_URL: ${RAG_BASE_URL:-http://host.docker.internal:5050}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nats:
condition: service_started
minio:
condition: service_healthy
networks:
- panda-wiki
# Nginx 反向代理 (可选,用于统一入口)
nginx:
image: nginx:alpine
container_name: panda-wiki-nginx
restart: unless-stopped
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "80:80"
depends_on:
- api
networks:
- panda-wiki
volumes:
pg_data:
redis_data:
minio_data:
networks:
panda-wiki:
driver: bridge
```
### 创建 Nginx 反向代理配置
```bash
cat > nginx.conf << 'EOF'
server {
listen 80;
server_name _;
client_max_body_size 100M;
# API 服务
location /api/ {
proxy_pass http://panda-wiki-api:8000;
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;
}
location /share/ {
proxy_pass http://panda-wiki-api:8000;
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;
}
# 健康检查
location /health {
proxy_pass http://panda-wiki-api:8000;
}
}
EOF
```
### 创建环境变量文件
```bash
cat > .env << 'EOF'
# 数据库密码
POSTGRES_PASSWORD=ChangeMe123!
# Redis 密码
REDIS_PASSWORD=ChangeMe123!
# NATS 密码
NATS_USER=panda-wiki
NATS_PASSWORD=ChangeMe123!
# MinIO/S3
S3_ACCESS_KEY=s3panda-wiki
S3_SECRET_KEY=ChangeMe123!
# JWT 密钥 (务必修改为随机字符串)
JWT_SECRET=your-jwt-secret-change-me-to-random-string
# 管理员初始密码 (首次登录后修改)
ADMIN_PASSWORD=admin123
# 日志级别: -4=debug, 0=info, 4=warn, 8=error
LOG_LEVEL=0
# RAG 向量检索服务地址
RAG_BASE_URL=http://host.docker.internal:5050
EOF
```
---
## 五、构建并启动
### 5.1 构建后端 Docker 镜像
```bash
cd ~/PandaWiki
# 构建 API 镜像 (包含数据库迁移)
docker build -f backend/Dockerfile.api -t panda-wiki-api:latest ./backend
# 构建 Consumer 镜像
docker build -f backend/Dockerfile.consumer -t panda-wiki-consumer:latest ./backend
```
### 5.2 构建前端 (可选)
如果需要在服务器上运行前端:
```bash
# 安装 Node.js 22 (管理员前端构建)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# 安装 pnpm
sudo npm install -g pnpm
# 构建管理员前端
cd ~/PandaWiki/web
pnpm install
pnpm --filter panda-wiki-admin build
# 构建用户端前端
pnpm --filter panda-wiki-app build
# 管理员前端会输出到 web/admin/dist/
# 用户端前端会输出到 web/app/dist/
# 可以用 Nginx 托管这些静态文件
```
### 5.3 启动全部服务
```bash
cd ~/PandaWiki
# 先启动基础设施
docker compose up -d postgres redis nats minio
# 等待基础设施就绪
sleep 15
# 启动业务服务
docker compose up -d api consumer nginx
# 查看所有容器状态
docker compose ps
# 查看日志
docker compose logs -f api
```
### 5.4 验证部署
```bash
# 检查 API 是否正常
curl http://localhost:8000/api/v1/health
# 查看容器日志
docker compose logs api | tail -50
docker compose logs consumer | tail -50
# 确认数据库迁移成功
docker compose logs api | grep -i migrate
```
---
## 六、AI 模型配置
首次登录管理后台后,需要配置 AI 大模型才能使用 AI 创作、AI 问答等功能。
### 支持的模型接入方式
| 方式 | 说明 |
|------|------|
| OpenAI 兼容 API | 任何兼容 OpenAI 接口的模型服务 |
| 本地 Ollama | 在内网服务器上自建 Ollama 服务 |
| DeepSeek API | DeepSeek 官方 API |
| Gemini API | Google Gemini |
### 内网环境推荐:自建 Ollama
```bash
# 在服务器上安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型 (根据服务器配置选择)
ollama pull qwen2.5:7b # 7B 参数,需要约 8GB 显存/内存
ollama pull qwen2.5:14b # 14B 参数
ollama pull llama3.1:8b # 8B 参数
# Ollama API 默认监听 11434 端口
# 在 PandaWiki 管理后台配置模型时,填写:
# API 地址: http://host.docker.internal:11434/v1
# 模型名称: qwen2.5:7b
```
---
## 七、Nginx 前端托管 (可选)
将构建好的前端静态文件用 Nginx 托管:
```bash
# 创建前端部署目录
sudo mkdir -p /var/www/panda-wiki/{admin,app}
# 复制构建产物
sudo cp -r ~/PandaWiki/web/admin/dist/* /var/www/panda-wiki/admin/
sudo cp -r ~/PandaWiki/web/app/dist/* /var/www/panda-wiki/app/
# Nginx 配置
sudo tee /etc/nginx/sites-available/panda-wiki << 'EOF'
server {
listen 80;
server_name your-domain.com;
client_max_body_size 100M;
# 管理后台
location /admin {
alias /var/www/panda-wiki/admin;
index index.html;
try_files $uri $uri/ /admin/index.html;
}
# Wiki 用户端
location / {
root /var/www/panda-wiki/app;
index index.html;
try_files $uri $uri/ /index.html;
}
# API 代理
location /api/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /share/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/panda-wiki /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
---
## 八、内网完全离线部署
如果服务器**完全无法访问外网**,需要在有网络的机器上预先准备所有材料。
### 8.1 准备阶段 (在有网络的机器上)
```bash
# 1. 拉取所有基础 Docker 镜像
docker pull postgres:16-alpine
docker pull redis:7-alpine
docker pull nats:2-alpine
docker pull minio/minio:latest
docker pull nginx:alpine
docker pull golang:1.24.3-alpine
docker pull alpine:3.21
# 2. 导出镜像为 tar 文件
docker save -o postgres-16.tar postgres:16-alpine
docker save -o redis-7.tar redis:7-alpine
docker save -o nats-2.tar nats:2-alpine
docker save -o minio-latest.tar minio/minio:latest
docker save -o nginx-alpine.tar nginx:alpine
docker save -o golang-1.24.tar golang:1.24.3-alpine
docker save -o alpine-3.21.tar alpine:3.21
# 3. 下载 Go 依赖 (可选Docker 构建时会自动处理)
# 如果有网络,直接 Docker build 即可
# 如果完全离线,需要预先 go mod download 并复制缓存
# 4. 打包项目源码
cd ~/PandaWiki
tar czf panda-wiki-source.tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='web/.pnpm-store' \
.
# 5. 将镜像 tar 和源码 tar 传输到内网服务器
scp *.tar user@internal-server:/home/user/
```
### 8.2 部署阶段 (在内网服务器上)
```bash
# 1. 导入 Docker 镜像
cd /home/user
for f in *.tar; do
docker load -i "$f"
done
# 2. 解压项目源码
mkdir -p ~/PandaWiki && cd ~/PandaWiki
tar xzf ~/panda-wiki-source.tar.gz
# 3. 修改 docker-compose.yml 中的 build 部分
# 将 BUILDKIT 缓存挂载移除 (离线环境不支持)
# 将 Dockerfile 中的 --mount=type=cache 替换为普通 COPY
# 4. 创建离线版 Dockerfile
cat > backend/Dockerfile.api.offline << 'DOCKERFILE'
FROM golang:1.24.3-alpine AS builder
WORKDIR /src
ENV CGO_ENABLED=0
COPY backend/go.mod backend/go.sum ./
RUN go mod download
COPY backend/ .
ARG TARGETOS TARGETARCH VERSION
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -extldflags '-static'" \
-o /build/panda-wiki-api \
cmd/api/main.go cmd/api/wire_gen.go \
&& GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -extldflags '-static'" \
-o /build/panda-wiki-migrate \
cmd/migrate/main.go cmd/migrate/wire_gen.go
FROM alpine:3.21 AS api
RUN apk update && apk upgrade && apk add --no-cache ca-certificates tzdata \
&& update-ca-certificates 2>/dev/null || true && rm -rf /var/cache/apk/*
WORKDIR /app
COPY --from=builder /build/panda-wiki-api /app/panda-wiki-api
COPY --from=builder /build/panda-wiki-migrate /app/panda-wiki-migrate
COPY --from=builder /src/store/pg/migration /app/migration
CMD ["sh", "-c", "/app/panda-wiki-migrate && /app/panda-wiki-api"]
DOCKERFILE
# 5. 使用离线 Dockerfile 构建
docker build -f backend/Dockerfile.api.offline -t panda-wiki-api:latest .
# 6. 启动服务
docker compose up -d
```
---
## 九、常用运维命令
```bash
# 查看所有服务状态
docker compose ps
# 查看某个服务的实时日志
docker compose logs -f api
docker compose logs -f consumer
# 重启某个服务
docker compose restart api
# 进入容器调试
docker exec -it panda-wiki-api sh
# 数据库备份
docker exec panda-wiki-postgres pg_dump -U panda-wiki panda-wiki > backup.sql
# 数据库恢复
docker exec -i panda-wiki-postgres psql -U panda-wiki panda-wiki < backup.sql
# 更新代码后重新构建
docker compose build api consumer
docker compose up -d api consumer
# 查看资源占用
docker stats
# 完全停止
docker compose down
# 停止并删除数据卷 (危险!会丢失所有数据)
docker compose down -v
```
---
## 十、访问地址
部署完成后:
| 地址 | 说明 |
|------|------|
| `http://服务器IP:8000` | 后端 API (通过 Nginx 代理则为 80 端口) |
| `http://服务器IP:2443` | 管理后台 (如使用官方 Caddy 配置) |
| `http://服务器IP:9001` | MinIO 管理控制台 |
首次登录使用 `.env` 中配置的 `ADMIN_PASSWORD` 密码,用户名为 `admin`
---
## 十一、故障排查
### 数据库连接失败
```bash
# 检查 postgres 是否就绪
docker compose logs postgres
# 手动连接测试
docker exec -it panda-wiki-postgres psql -U panda-wiki -d panda-wiki
```
### API 启动失败
```bash
# 查看详细日志
docker compose logs api
# 常见原因:
# 1. 数据库迁移失败 - 检查 PG_DSN 配置
# 2. NATS 连接失败 - 检查 MQ_NATS_SERVER 配置
# 3. Redis 连接失败 - 检查 REDIS_ADDR 配置
```
### 前端页面空白
```bash
# 检查 API 是否可达
curl http://localhost:8000/api/v1/health
# 检查浏览器控制台是否有 CORS 或 API 404 错误
# 确保前端配置的 API 地址正确
```
### 容器之间网络不通
```bash
# 检查网络
docker network inspect panda-wiki_panda-wiki
# 容器间通信测试
docker exec panda-wiki-api ping panda-wiki-postgres
```