open-webui/docs/DOCKER-DEPLOYMENT.md
2025-11-15 09:01:45 +08:00

1088 lines
25 KiB
Markdown
Raw 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.

# Open WebUI Docker 生产环境部署指南
本指南介绍如何在生产环境中部署 Open WebUI Docker 镜像,并连接到外部 MySQL 数据库。
## 目录
- [镜像说明](#镜像说明)
- [镜像获取方式](#镜像获取方式)
- [前置准备](#前置准备)
- [快速开始](#快速开始)
- [MySQL 数据库配置](#mysql-数据库配置)
- [环境变量完整列表](#环境变量完整列表)
- [高级配置](#高级配置)
- [故障排查](#故障排查)
---
## 镜像说明
### 镜像仓库
```
ghcr.io/<your-username>/open-webui-next:slim
```
### 镜像特性
- **架构**: linux/amd64 (x86_64)
- **变体**: Slim 精简版(不预装 AI 模型,首次运行时自动下载)
- **包含**: 前端 (SvelteKit) + 后端 (FastAPI)
- **不包含**: 数据库服务(需要外部 MySQL
### 镜像标签规则
| 标签 | 说明 | 示例 |
|------|------|------|
| `slim` | 主分支最新精简版 | `ghcr.io/user/repo:slim` |
| `main-slim` | 主分支最新构建 | `ghcr.io/user/repo:main-slim` |
| `v1.2.3-slim` | 版本标签 | `ghcr.io/user/repo:v1.2.3-slim` |
| `git-abc1234-slim` | Git commit SHA | `ghcr.io/user/repo:git-abc1234-slim` |
---
## 镜像获取方式
### 从 GitHub Container Registry (GHCR) 拉取
#### 方式一:拉取公开镜像(推荐)
如果仓库是公开的,直接拉取即可:
```bash
# 拉取最新 slim 版本
docker pull ghcr.io/<your-username>/open-webui-next:slim
# 拉取特定版本标签
docker pull ghcr.io/<your-username>/open-webui-next:v1.2.3-slim
# 拉取特定 Git commit
docker pull ghcr.io/<your-username>/open-webui-next:git-abc1234-slim
```
验证镜像拉取成功:
```bash
# 查看本地镜像列表
docker images | grep open-webui-next
# 查看镜像详细信息
docker inspect ghcr.io/<your-username>/open-webui-next:slim
```
#### 方式二:拉取私有镜像(需要认证)
如果仓库是私有的,需要先登录 GHCR
**步骤 1: 创建 GitHub Personal Access Token (PAT)**
1. 访问 GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
2. 点击 "Generate new token (classic)"
3. 设置以下权限:
- `read:packages` - 读取容器镜像
- `write:packages` - (可选) 推送镜像
4. 生成并保存 Token (只显示一次)
**步骤 2: 登录 GHCR**
```bash
# 使用 PAT 登录
echo "YOUR_PERSONAL_ACCESS_TOKEN" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin
# 或交互式输入密码
docker login ghcr.io -u YOUR_GITHUB_USERNAME
# Password: [输入 PAT]
```
登录成功后会显示:
```
Login Succeeded
```
**步骤 3: 拉取镜像**
```bash
docker pull ghcr.io/<your-username>/open-webui-next:slim
```
**步骤 4: 退出登录(可选)**
```bash
docker logout ghcr.io
```
### 生产服务器部署流程
#### 场景一:单服务器部署
```bash
# 1. SSH 登录生产服务器
ssh user@production-server
# 2. 登录 GHCR (如果是私有仓库)
echo "YOUR_PAT" | docker login ghcr.io -u YOUR_USERNAME --password-stdin
# 3. 拉取最新镜像
docker pull ghcr.io/<your-username>/open-webui-next:slim
# 4. 停止旧容器 (如果存在)
docker stop open-webui || true
docker rm open-webui || true
# 5. 启动新容器
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
-e DATABASE_URL="mysql://..." \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/<your-username>/open-webui-next:slim
# 6. 验证部署
docker ps | grep open-webui
curl -f http://localhost:8080/health || echo "Health check failed"
```
#### 场景二CI/CD 自动化部署
**GitHub Actions 自动部署示例**:
```yaml
# .github/workflows/deploy.yml
name: Deploy to Production
on:
workflow_run:
workflows: ["Build and Push Docker Image (Production)"]
types:
- completed
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.PROD_SERVER_HOST }}
username: ${{ secrets.PROD_SERVER_USER }}
key: ${{ secrets.PROD_SERVER_SSH_KEY }}
script: |
# 拉取最新镜像
docker pull ghcr.io/${{ github.repository }}:slim
# 滚动更新
docker stop open-webui || true
docker rm open-webui || true
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
--env-file /opt/openwebui/.env \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/${{ github.repository }}:slim
# 健康检查
sleep 10
docker ps | grep open-webui
curl -f http://localhost:8080/health
```
#### 场景三:多服务器部署(使用镜像同步)
如果有多台服务器,可以先拉取到一台,然后导出/导入:
```bash
# 服务器 A: 从 GHCR 拉取
docker pull ghcr.io/<your-username>/open-webui-next:slim
# 导出镜像到文件
docker save ghcr.io/<your-username>/open-webui-next:slim | gzip > open-webui-slim.tar.gz
# 传输到其他服务器
scp open-webui-slim.tar.gz user@server-b:/tmp/
scp open-webui-slim.tar.gz user@server-c:/tmp/
# 服务器 B/C: 导入镜像
gunzip -c /tmp/open-webui-slim.tar.gz | docker load
```
### 镜像更新策略
#### 自动更新(使用 Watchtower
```bash
# 部署 Watchtower 容器监控镜像更新
docker run -d \
--name watchtower \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--interval 3600 \
--cleanup \
open-webui
```
Watchtower 会每小时检查一次 `open-webui` 容器的镜像更新,如果有新版本会自动拉取并重启容器。
#### 手动更新(推荐生产环境)
```bash
# 1. 拉取最新镜像
docker pull ghcr.io/<your-username>/open-webui-next:slim
# 2. 检查镜像是否有更新
OLD_ID=$(docker inspect --format='{{.Image}}' open-webui)
NEW_ID=$(docker inspect --format='{{.Id}}' ghcr.io/<your-username>/open-webui-next:slim)
if [ "$OLD_ID" != "$NEW_ID" ]; then
echo "New image available, updating..."
# 3. 备份当前容器配置
docker inspect open-webui > /backup/open-webui-config-$(date +%Y%m%d).json
# 4. 停止并删除旧容器
docker stop open-webui
docker rm open-webui
# 5. 启动新容器
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
--env-file /opt/openwebui/.env \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/<your-username>/open-webui-next:slim
# 6. 清理旧镜像
docker image prune -f
else
echo "Already up to date"
fi
```
### 镜像访问故障排查
#### 问题 1: 拉取失败 - 认证错误
```
Error response from daemon: unauthorized: authentication required
```
**解决方案**:
- 检查是否已登录: `docker info | grep Username`
- 重新登录: `docker login ghcr.io -u YOUR_USERNAME`
- 确认 PAT 有 `read:packages` 权限
- 确认仓库可见性(公开/私有)
#### 问题 2: 拉取失败 - 网络超时
```
Error response from daemon: Get https://ghcr.io/v2/: dial tcp: i/o timeout
```
**解决方案**:
```bash
# 检查 DNS 解析
nslookup ghcr.io
# 检查网络连接
ping ghcr.io
curl -I https://ghcr.io
# 配置 Docker 镜像代理(如果在国内服务器)
# /etc/docker/daemon.json
{
"registry-mirrors": [
"https://mirror.gcr.io"
]
}
# 重启 Docker
sudo systemctl restart docker
```
#### 问题 3: 拉取失败 - 镜像不存在
```
Error response from daemon: manifest for ghcr.io/user/repo:slim not found
```
**解决方案**:
- 确认镜像名称和标签拼写正确
- 检查 GitHub Actions 构建是否成功
- 查看仓库 Packages 页面确认镜像已发布
- 使用 `docker search ghcr.io/<your-username>` 搜索可用镜像
#### 问题 4: 权限不足
```
Error response from daemon: pull access denied for ghcr.io/user/repo
```
**解决方案**:
- 确认 GitHub 用户有仓库访问权限
- 如果是组织仓库,确认用户在组织中
- 管理员在仓库 Settings → Actions → General → Workflow permissions 中启用 "Read and write permissions"
---
## 前置准备
### 1. MySQL 数据库准备
在您的 MySQL 服务器上创建数据库和用户:
```sql
-- 创建数据库
CREATE DATABASE openwebui CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建用户并授权(替换密码)
CREATE USER 'openwebui'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON openwebui.* TO 'openwebui'@'%';
FLUSH PRIVILEGES;
-- 验证创建
SHOW DATABASES LIKE 'openwebui';
SELECT User, Host FROM mysql.user WHERE User = 'openwebui';
```
**安全建议**:
- 生产环境使用强密码(至少 16 位,包含大小写字母、数字、特殊字符)
- 如果 MySQL 和 Docker 在同一网络,限制 `Host` 为具体 IP 而非 `%`
- 启用 MySQL SSL 连接(见高级配置)
### 2. 网络连通性检查
确保 Docker 容器可以访问 MySQL 服务器:
```bash
# 在 Docker 宿主机测试 MySQL 连接
mysql -h <mysql_host> -P 3306 -u openwebui -p
# 或使用 telnet 测试端口
telnet <mysql_host> 3306
```
### 3. 数据持久化目录
创建用于挂载的数据目录:
```bash
mkdir -p /data/open-webui/data
chmod 755 /data/open-webui/data
```
---
## 快速开始
### 方式一:使用环境变量(推荐)
```bash
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
-e DATABASE_URL="mysql://openwebui:your_secure_password@mysql.example.com:3306/openwebui" \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/<your-username>/open-webui-next:slim
```
### 方式二:使用分离的数据库环境变量
```bash
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
-e DATABASE_TYPE="mysql" \
-e DATABASE_HOST="mysql.example.com" \
-e DATABASE_PORT="3306" \
-e DATABASE_NAME="openwebui" \
-e DATABASE_USER="openwebui" \
-e DATABASE_PASSWORD="your_secure_password" \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/<your-username>/open-webui-next:slim
```
### 方式三:使用 .env 文件(推荐生产环境)
创建 `.env` 文件:
```bash
# .env
DATABASE_URL=mysql://openwebui:your_secure_password@mysql.example.com:3306/openwebui
WEBUI_NAME=Open WebUI Production
WEBUI_SECRET_KEY=your_random_secret_key_here
```
运行容器:
```bash
docker run -d \
--name open-webui \
--restart unless-stopped \
-p 8080:8080 \
--env-file .env \
-v /data/open-webui/data:/app/backend/data \
ghcr.io/<your-username>/open-webui-next:slim
```
---
## MySQL 数据库配置
### 数据库连接方式
#### 选项 1: 使用完整 DATABASE_URL推荐
```bash
# 标准 MySQL 连接
DATABASE_URL=mysql://username:password@host:port/database
# 带参数的连接UTF-8 编码)
DATABASE_URL=mysql://username:password@host:port/database?charset=utf8mb4
# MySQL 8.0+ 使用 PyMySQL 驱动
DATABASE_URL=mysql+pymysql://username:password@host:port/database
# SSL 连接
DATABASE_URL=mysql://username:password@host:port/database?ssl=true
```
#### 选项 2: 使用分离的环境变量
```bash
DATABASE_TYPE=mysql # 数据库类型
DATABASE_HOST=mysql.example.com # 主机地址
DATABASE_PORT=3306 # 端口
DATABASE_NAME=openwebui # 数据库名
DATABASE_USER=openwebui # 用户名
DATABASE_PASSWORD=password # 密码
```
### 支持的数据库类型
| 数据库 | DATABASE_TYPE | 驱动 | 示例 URL |
|--------|---------------|------|----------|
| MySQL 5.7+ | `mysql` | mysqlclient | `mysql://user:pass@host/db` |
| MySQL 8.0+ | `mysql+pymysql` | pymysql | `mysql+pymysql://user:pass@host/db` |
| PostgreSQL | `postgresql` | psycopg2 | `postgresql://user:pass@host/db` |
| SQLite | `sqlite` | 内置 | `sqlite:///path/to/db.db` |
### 数据库性能优化
#### 连接池配置
```bash
# 连接池大小默认10
DATABASE_POOL_SIZE=20
# 最大溢出连接数默认0
DATABASE_POOL_MAX_OVERFLOW=10
# 连接回收时间(秒,防止断线)
DATABASE_POOL_RECYCLE=3600
# 连接超时时间(秒)
DATABASE_CONNECT_TIMEOUT=10
```
#### MySQL 特定优化
在 MySQL 服务器配置文件 `my.cnf` 中:
```ini
[mysqld]
# 连接数限制
max_connections = 500
# InnoDB 缓冲池大小(推荐物理内存的 50-70%
innodb_buffer_pool_size = 2G
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# 二进制日志(用于备份和恢复)
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7
```
---
## 环境变量完整列表
### 数据库配置
| 环境变量 | 说明 | 默认值 | 示例 |
|---------|------|--------|------|
| `DATABASE_URL` | 完整数据库连接 URL | `sqlite:///{DATA_DIR}/webui.db` | `mysql://user:pass@host/db` |
| `DATABASE_TYPE` | 数据库类型 | - | `mysql`, `postgresql` |
| `DATABASE_HOST` | 数据库主机 | - | `mysql.example.com` |
| `DATABASE_PORT` | 数据库端口 | - | `3306` |
| `DATABASE_NAME` | 数据库名称 | - | `openwebui` |
| `DATABASE_USER` | 数据库用户名 | - | `openwebui` |
| `DATABASE_PASSWORD` | 数据库密码 | - | `password` |
| `DATABASE_SCHEMA` | 数据库 Schema | - | `public` |
| `DATABASE_POOL_SIZE` | 连接池大小 | `10` | `20` |
| `DATABASE_POOL_MAX_OVERFLOW` | 最大溢出连接 | `0` | `10` |
### 应用基础配置
| 环境变量 | 说明 | 默认值 | 示例 |
|---------|------|--------|------|
| `WEBUI_NAME` | 应用名称 | `Open WebUI` | `My AI Platform` |
| `WEBUI_URL` | 外部访问 URL | `http://localhost:8080` | `https://ai.example.com` |
| `WEBUI_SECRET_KEY` | JWT 密钥(必须设置) | 自动生成 | 随机字符串 |
| `PORT` | 服务端口 | `8080` | `8080` |
| `HOST` | 监听地址 | `0.0.0.0` | `0.0.0.0` |
| `DATA_DIR` | 数据目录 | `/app/backend/data` | - |
### 认证与安全
| 环境变量 | 说明 | 默认值 | 示例 |
|---------|------|--------|------|
| `WEBUI_AUTH` | 启用认证 | `true` | `true`, `false` |
| `WEBUI_AUTH_TRUSTED_EMAIL_HEADER` | 信任的邮箱 Header | - | `X-User-Email` |
| `DEFAULT_USER_ROLE` | 默认用户角色 | `pending` | `user`, `admin` |
| `ENABLE_SIGNUP` | 允许注册 | `true` | `true`, `false` |
| `JWT_EXPIRES_IN` | JWT 过期时间 | `30d` | `7d`, `24h` |
### LLM 提供商配置
| 环境变量 | 说明 | 默认值 |
|---------|------|--------|
| `OPENAI_API_BASE_URL` | OpenAI API 基础 URL | `https://api.openai.com/v1` |
| `OPENAI_API_KEY` | OpenAI API 密钥 | - |
| `OLLAMA_BASE_URL` | Ollama 服务地址 | `http://localhost:11434` |
| `ANTHROPIC_API_KEY` | Claude API 密钥 | - |
| `GOOGLE_API_KEY` | Gemini API 密钥 | - |
### RAG向量数据库配置
| 环境变量 | 说明 | 默认值 |
|---------|------|--------|
| `VECTOR_DB` | 向量数据库类型 | `chroma` |
| `CHROMA_DATA_PATH` | ChromaDB 数据路径 | `{DATA_DIR}/vector_db` |
| `QDRANT_URI` | Qdrant 连接地址 | - |
| `OPENSEARCH_URI` | OpenSearch 连接地址 | - |
### 日志配置
| 环境变量 | 说明 | 默认值 |
|---------|------|--------|
| `GLOBAL_LOG_LEVEL` | 全局日志级别 | `INFO` |
| `LOG_LEVEL` | 应用日志级别 | `INFO` |
| `UVICORN_LOG_LEVEL` | Uvicorn 日志级别 | `info` |
---
## 高级配置
### 1. 使用 Docker Compose推荐
创建 `docker-compose.yml`
```yaml
version: '3.8'
services:
open-webui:
image: ghcr.io/<your-username>/open-webui-next:slim
container_name: open-webui
restart: unless-stopped
ports:
- "8080:8080"
environment:
# 数据库配置
DATABASE_URL: mysql://openwebui:${DB_PASSWORD}@mysql.example.com:3306/openwebui
# 应用配置
WEBUI_NAME: "Open WebUI Production"
WEBUI_SECRET_KEY: ${WEBUI_SECRET_KEY}
WEBUI_URL: https://ai.example.com
# 认证配置
ENABLE_SIGNUP: "false"
DEFAULT_USER_ROLE: "pending"
# LLM 配置
OPENAI_API_KEY: ${OPENAI_API_KEY}
OLLAMA_BASE_URL: http://ollama:11434
# 日志配置
GLOBAL_LOG_LEVEL: INFO
volumes:
- /data/open-webui/data:/app/backend/data
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 资源限制
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2G
# 可选:如果需要在同一网络部署 Ollama
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
volumes:
- /data/ollama:/root/.ollama
deploy:
resources:
limits:
memory: 8G
```
创建 `.env` 文件(不要提交到 Git
```bash
# .env
DB_PASSWORD=your_secure_mysql_password
WEBUI_SECRET_KEY=your_random_secret_key_here
OPENAI_API_KEY=sk-your-openai-key
```
启动服务:
```bash
docker-compose up -d
```
### 2. MySQL SSL 连接
如果 MySQL 启用了 SSL配置连接
```bash
# 方式 1: 在 DATABASE_URL 中指定
DATABASE_URL="mysql://user:pass@host/db?ssl=true&ssl_ca=/path/to/ca-cert.pem"
# 方式 2: 使用环境变量
DATABASE_SSL=true
DATABASE_SSL_CA=/path/to/ca-cert.pem
DATABASE_SSL_CERT=/path/to/client-cert.pem
DATABASE_SSL_KEY=/path/to/client-key.pem
```
挂载证书到容器:
```bash
docker run -d \
-v /path/to/certs:/certs:ro \
-e DATABASE_URL="mysql://user:pass@host/db?ssl_ca=/certs/ca-cert.pem" \
ghcr.io/<your-username>/open-webui-next:slim
```
### 3. 反向代理Nginx
生产环境推荐在 Docker 前配置 Nginx 反向代理:
```nginx
# /etc/nginx/sites-available/openwebui
upstream open_webui {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name ai.example.com;
# HTTPS 重定向
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name ai.example.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 日志
access_log /var/log/nginx/openwebui_access.log;
error_log /var/log/nginx/openwebui_error.log;
# 客户端最大请求体大小(上传文件)
client_max_body_size 100M;
location / {
proxy_pass http://open_webui;
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;
# WebSocket 支持(用于实时聊天)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时配置
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}
```
启用配置:
```bash
sudo ln -s /etc/nginx/sites-available/openwebui /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### 4. 数据备份策略
#### MySQL 数据库备份
```bash
#!/bin/bash
# backup-mysql.sh
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/openwebui_$DATE.sql.gz"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份数据库
mysqldump -h mysql.example.com -u openwebui -p openwebui | gzip > $BACKUP_FILE
# 删除 7 天前的备份
find $BACKUP_DIR -name "openwebui_*.sql.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_FILE"
```
设置 cron 定时任务:
```bash
# 每天凌晨 2 点备份
0 2 * * * /path/to/backup-mysql.sh
```
#### 数据目录备份
```bash
#!/bin/bash
# backup-data.sh
BACKUP_DIR="/backup/openwebui"
DATE=$(date +%Y%m%d_%H%M%S)
DATA_DIR="/data/open-webui/data"
mkdir -p $BACKUP_DIR
# 备份数据目录(包含上传的文件、模型等)
tar -czf "$BACKUP_DIR/data_$DATE.tar.gz" -C "$DATA_DIR" .
# 删除 30 天前的备份
find $BACKUP_DIR -name "data_*.tar.gz" -mtime +30 -delete
echo "Data backup completed: $BACKUP_DIR/data_$DATE.tar.gz"
```
### 5. 监控与告警
#### 健康检查脚本
```bash
#!/bin/bash
# healthcheck.sh
HEALTH_URL="http://localhost:8080/health"
MAX_RETRIES=3
RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)
if [ $HTTP_CODE -eq 200 ]; then
echo "Health check passed"
exit 0
fi
RETRY_COUNT=$((RETRY_COUNT + 1))
sleep 5
done
echo "Health check failed after $MAX_RETRIES retries"
exit 1
```
#### Docker 健康检查
`docker-compose.yml` 中已配置健康检查:
```bash
# 查看健康状态
docker ps | grep open-webui
# 查看健康检查日志
docker inspect --format='{{json .State.Health}}' open-webui | jq
```
---
## 故障排查
### 1. 数据库连接失败
**症状**: 容器启动后立即退出,日志显示数据库连接错误
**排查步骤**:
```bash
# 查看容器日志
docker logs open-webui
# 进入容器测试数据库连接
docker exec -it open-webui bash
apt-get update && apt-get install -y mysql-client
mysql -h mysql.example.com -u openwebui -p
```
**常见问题**:
- ✅ 确认 MySQL 用户权限:`GRANT ALL PRIVILEGES ON openwebui.* TO 'openwebui'@'%'`
- ✅ 确认防火墙规则:允许 Docker 容器 IP 访问 MySQL 3306 端口
- ✅ 确认 `DATABASE_URL` 格式正确
- ✅ 如果使用 MySQL 8.0,尝试 `mysql+pymysql://` 驱动
### 2. 模型下载失败Slim 镜像首次运行)
**症状**: 应用启动缓慢,日志显示模型下载错误
**解决方案**:
```bash
# 方式 1: 预先下载模型到挂载目录
# 在宿主机上执行
mkdir -p /data/open-webui/data/cache
cd /data/open-webui/data/cache
# 下载 sentence-transformers 模型
wget https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main/pytorch_model.bin
# 方式 2: 设置 HuggingFace 镜像
docker run -d \
-e HF_ENDPOINT=https://hf-mirror.com \
...
```
### 3. 容器内存不足
**症状**: 容器频繁重启,日志显示 OOM (Out of Memory)
**解决方案**:
```bash
# 限制容器内存使用
docker run -d \
--memory="4g" \
--memory-swap="4g" \
...
# 或在 docker-compose.yml 中配置资源限制(见高级配置)
```
### 4. 文件上传失败
**症状**: 上传大文件时出现 413 错误
**解决方案**:
```bash
# 如果使用 Nginx 反向代理,增加上传大小限制
# /etc/nginx/nginx.conf
http {
client_max_body_size 100M;
}
# 重启 Nginx
sudo systemctl reload nginx
```
### 5. WebSocket 连接断开
**症状**: 实时聊天功能不工作,日志显示 WebSocket 错误
**解决方案**:
检查 Nginx 配置是否支持 WebSocket
```nginx
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
...
}
```
### 6. 数据库迁移错误
**症状**: 从 SQLite 迁移到 MySQL 后数据丢失
**解决方案**:
Open WebUI 不支持自动数据迁移,需要手动导出导入:
```bash
# 1. 从旧容器导出数据(使用 SQLite
docker exec old-container python -m open_webui.utils.export_data > data.json
# 2. 启动新容器(使用 MySQL
docker run -d \
-e DATABASE_URL=mysql://... \
--name new-container \
ghcr.io/<your-username>/open-webui-next:slim
# 3. 导入数据
docker exec -i new-container python -m open_webui.utils.import_data < data.json
```
---
## 维护操作
### 更新镜像
```bash
# 拉取最新镜像
docker pull ghcr.io/<your-username>/open-webui-next:slim
# 停止并删除旧容器
docker stop open-webui
docker rm open-webui
# 启动新容器(数据卷保留)
docker run -d \
--name open-webui \
... # 相同参数
ghcr.io/<your-username>/open-webui-next:slim
```
### 查看日志
```bash
# 实时查看日志
docker logs -f open-webui
# 查看最近 100 行日志
docker logs --tail 100 open-webui
# 查看特定时间范围日志
docker logs --since "2024-01-01T00:00:00" open-webui
```
### 进入容器调试
```bash
# 进入容器 bash
docker exec -it open-webui bash
# 查看环境变量
docker exec open-webui env
# 查看进程
docker exec open-webui ps aux
```
---
## 安全建议
1. **不要在 DATABASE_URL 中明文暴露密码**
- 使用 Docker secrets 或环境变量文件
- `.env` 文件添加到 `.gitignore`
2. **定期更新镜像**
- 订阅 GitHub 仓库 Release 通知
- 定期执行 `docker pull` 更新
3. **限制容器权限**
```bash
docker run -d \
--security-opt=no-new-privileges \
--cap-drop=ALL \
--read-only \
--tmpfs /tmp \
...
```
4. **使用 HTTPS**
- 生产环境必须使用 HTTPSNginx + Let's Encrypt
- 设置 `WEBUI_URL=https://...`
5. **禁用不必要的功能**
```bash
-e ENABLE_SIGNUP=false # 禁止公开注册
-e ENABLE_API_KEY=true # 启用 API Key 认证
```
---
## 性能优化建议
### 1. 数据库优化
- 使用 MySQL 8.0+ 以获得更好性能
- 启用 InnoDB 缓冲池:`innodb_buffer_pool_size = 2G`
- 定期执行 `OPTIMIZE TABLE` 优化表
### 2. 应用优化
```bash
# 增加 Worker 数量(根据 CPU 核心数)
-e UVICORN_WORKERS=4
# 增加数据库连接池
-e DATABASE_POOL_SIZE=20
-e DATABASE_POOL_MAX_OVERFLOW=10
```
### 3. 缓存优化
```bash
# 启用 Redis 缓存(可选)
-e REDIS_URL=redis://redis:6379/0
# 增加 AI 模型缓存
-v /data/open-webui/cache:/root/.cache
```
---
## 联系与支持
- **文档**: 项目 README.md 和 CLAUDE.md
- **问题反馈**: GitHub Issues
- **社区讨论**: GitHub Discussions
---
**最后更新**: 2024-11-14