From 177ddc99f35990a0fb17dade5dd6a174c6a7afbd Mon Sep 17 00:00:00 2001 From: wxy <3050128610@qq.com> Date: Thu, 21 May 2026 19:53:36 +0800 Subject: [PATCH] init push --- DEPLOY_UBUNTU22.md | 773 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 773 insertions(+) create mode 100644 DEPLOY_UBUNTU22.md diff --git a/DEPLOY_UBUNTU22.md b/DEPLOY_UBUNTU22.md new file mode 100644 index 0000000..1700c87 --- /dev/null +++ b/DEPLOY_UBUNTU22.md @@ -0,0 +1,773 @@ +# 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 +``` + +--- + +## 三、传输源码到服务器 + +### 方式 A:Git 仓库 (服务器有网络) + +```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 +```