RAG/docker-run.sh

361 lines
12 KiB
Bash
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.

#!/bin/bash
# Docker Run 启动脚本
# 用于在目标机器上启动已迁移的容器镜像
# 使用方法: ./docker-run.sh
set -e
echo "=== Docker 容器启动脚本 ==="
echo ""
# 检查 .env 文件是否存在
if [ ! -f ".env" ]; then
echo "Error: .env file not found!"
echo "Please create .env file from .env.example"
exit 1
fi
# 从 .env 文件读取端口配置
CHROMA_PORT=$(grep "^CHROMA_SERVER_PORT=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "8000")
CHROMA_HOST=$(grep "^CHROMA_SERVER_HOST=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "localhost")
API_PORT=$(grep "^API_PORT=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "8001")
API_HOST=$(grep "^API_HOST=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "0.0.0.0")
SOFFICE_HOST=$(grep "^SOFFICE_HOST=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "localhost")
SOFFICE_PORT=$(grep "^SOFFICE_PORT=" .env 2>/dev/null | cut -d'=' -f2 | tr -d ' ' || echo "8003")
# 调试:打印 SOFFICE_PORT 的值
echo "DEBUG: SOFFICE_PORT = '$SOFFICE_PORT'"
echo "DEBUG: CHROMA_PORT = '$CHROMA_PORT'"
echo "DEBUG: API_PORT = '$API_PORT'"
# 检查端口是否被占用
check_port() {
local port=$1
local service_name=$2
if command -v lsof >/dev/null 2>&1; then
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
echo "Warning: Port $port is already in use by another process"
echo " This port is required for $service_name"
echo ""
echo "To resolve this issue, you can:"
echo " 1. Stop the process using port $port:"
echo " sudo lsof -i :$port # Find the process"
echo " sudo kill <PID> # Kill the process"
echo ""
echo " 2. Or change the port in .env file:"
if [ "$service_name" = "ChromaDB" ]; then
echo " CHROMA_SERVER_PORT=<different_port>"
else
echo " API_PORT=<different_port>"
fi
echo ""
read -p "Do you want to continue anyway? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
elif command -v netstat >/dev/null 2>&1; then
if netstat -tuln 2>/dev/null | grep -q ":$port "; then
echo "Warning: Port $port appears to be in use"
echo " This port is required for $service_name"
echo ""
read -p "Do you want to continue anyway? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
fi
}
echo "检查端口占用情况..."
# 检查 ChromaDB 端口(从 .env 文件读取的配置端口)
check_port $CHROMA_PORT "ChromaDB"
# 检查 RAG API 端口
check_port $API_PORT "RAG API"
# 检查 Soffice Service 端口
check_port $SOFFICE_PORT "Soffice Service"
echo "✓ 端口检查完成"
echo ""
# 停止并删除已存在的容器
echo "1. 停止并删除已存在的容器..."
docker stop rag-api 2>/dev/null || true
docker rm rag-api 2>/dev/null || true
docker stop rag-chromadb 2>/dev/null || true
docker rm rag-chromadb 2>/dev/null || true
docker stop rag-soffice 2>/dev/null || true
docker rm rag-soffice 2>/dev/null || true
echo " ✓ 已停止并删除旧容器"
# 删除旧镜像
echo ""
echo "2. 删除旧镜像..."
docker rmi rag-rag-api:latest 2>/dev/null || true
docker rmi chromadb/chroma:latest 2>/dev/null || true
docker rmi rag-soffice-service:latest 2>/dev/null || true
echo " ✓ 已删除旧镜像"
# 加载新镜像
echo ""
echo "3. 加载新镜像..."
if [ -f "rag-api.tar.gz" ]; then
echo " 正在加载 rag-rag-api 镜像..."
gunzip -c rag-api.tar.gz | docker load
echo " ✓ rag-rag-api 镜像加载完成"
elif [ -f "rag-api.tar" ]; then
echo " 正在加载 rag-rag-api 镜像..."
docker load -i rag-api.tar
echo " ✓ rag-rag-api 镜像加载完成"
else
echo "Error: rag-rag-api 镜像文件不存在"
echo "请确保 rag-api.tar.gz 或 rag-api.tar 文件存在"
exit 1
fi
if [ -f "chromadb.tar.gz" ]; then
echo " 正在加载 chromadb 镜像..."
gunzip -c chromadb.tar.gz | docker load
echo " ✓ chromadb 镜像加载完成"
elif [ -f "chromadb.tar" ]; then
echo " 正在加载 chromadb 镜像..."
docker load -i chromadb.tar
echo " ✓ chromadb 镜像加载完成"
else
echo "Error: chromadb 镜像文件不存在"
echo "请确保 chromadb.tar.gz 或 chromadb.tar 文件存在"
exit 1
fi
if [ -f "soffice.tar.gz" ]; then
echo " 正在加载 soffice 镜像..."
gunzip -c soffice.tar.gz | docker load
echo " ✓ soffice 镜像加载完成"
elif [ -f "soffice.tar" ]; then
echo " 正在加载 soffice 镜像..."
docker load -i soffice.tar
echo " ✓ soffice 镜像加载完成"
else
echo "Error: soffice 镜像文件不存在"
echo "请确保 soffice.tar.gz 或 soffice.tar 文件存在"
exit 1
fi
# 检查镜像是否已加载
echo ""
echo "4. 验证镜像是否已加载..."
if ! docker images | grep -q "rag-rag-api"; then
echo "Error: rag-rag-api 镜像未加载"
exit 1
fi
CHROMA_TAG=$(docker images chromadb/chroma --format "{{.Repository}}:{{.Tag}}" | head -1)
if [ -z "$CHROMA_TAG" ]; then
echo "Error: chromadb 镜像未加载"
exit 1
fi
if ! docker images | grep -q "rag-soffice-service"; then
echo "Error: rag-soffice-service 镜像未加载"
exit 1
fi
echo " ✓ 所有镜像已加载"
# 创建必要的目录
echo ""
echo "5. 创建必要的目录..."
mkdir -p chroma_db_data logs
# 检查 databases_config.json 文件是否存在(如果使用多数据库配置)
DB_CONFIG_MOUNT=""
if [ -f "databases_config.json" ]; then
DB_CONFIG_MOUNT="-v $(pwd)/databases_config.json:/app/databases_config.json:ro"
echo " - 找到 databases_config.json将挂载到容器"
else
echo " - 未找到 databases_config.json如果使用多数据库配置请创建此文件"
fi
echo ""
echo "6. 启动 ChromaDB 容器..."
echo " 配置地址: $CHROMA_HOST:$CHROMA_PORT (从 .env 文件读取)"
# 停止并删除已存在的容器(如果存在)
docker stop rag-chromadb 2>/dev/null || true
docker rm rag-chromadb 2>/dev/null || true
# ChromaDB 配置说明
# 使用 bridge 网络模式,通过端口映射将容器内的 8000 端口映射到宿主机的 $CHROMA_PORT 端口
# 这样 ChromaDB 可以使用宿主机上的任意端口,不受固定 8000 端口的限制
echo " 端口映射: 宿主机 $CHROMA_PORT -> 容器内 8000"
docker run -d \
--name rag-chromadb \
-p $CHROMA_PORT:8000 \
-v $(pwd)/chroma_db_data:/data \
-e IS_PERSISTENT=TRUE \
-e ANONYMIZED_TELEMETRY=FALSE \
--restart unless-stopped \
"$CHROMA_TAG"
echo " ✓ ChromaDB 容器已启动 (宿主机端口: $CHROMA_PORT)"
# 启动 Soffice Service 容器
echo ""
echo "7. 启动 Soffice Service 容器..."
echo " 配置地址: localhost:$SOFFICE_PORT (从 .env 文件读取)"
# 停止并删除已存在的容器(如果存在)
docker stop rag-soffice 2>/dev/null || true
docker rm rag-soffice 2>/dev/null || true
# Soffice Service 使用端口映射
docker run -d \
--name rag-soffice \
-p $SOFFICE_PORT:8003 \
-e SOFFICE_PORT=$SOFFICE_PORT \
--restart unless-stopped \
rag-soffice-service:latest
echo " ✓ Soffice Service 容器已启动 (宿主机端口: $SOFFICE_PORT)"
# 等待 Soffice Service 启动并检查连接
echo ""
echo "8. 等待 Soffice Service 启动并检查连接..."
sleep 3
# 检查 Soffice Service 是否正在运行
MAX_WAIT=30
WAIT_COUNT=0
SOFFICE_READY=false
while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
if docker ps | grep -q "rag-soffice.*Up"; then
# 尝试连接 Soffice Service
if command -v curl >/dev/null 2>&1; then
if curl -s -f "http://localhost:$SOFFICE_PORT/health" >/dev/null 2>&1; then
SOFFICE_READY=true
break
fi
elif command -v nc >/dev/null 2>&1; then
if nc -z localhost $SOFFICE_PORT 2>/dev/null; then
SOFFICE_READY=true
break
fi
else
# 如果没有 curl 或 nc只检查容器是否运行
SOFFICE_READY=true
break
fi
fi
echo " 等待 Soffice Service 启动... ($WAIT_COUNT/$MAX_WAIT 秒)"
sleep 2
WAIT_COUNT=$((WAIT_COUNT + 2))
done
if [ "$SOFFICE_READY" = true ]; then
echo " ✓ Soffice Service 已就绪 (宿主机端口: $SOFFICE_PORT)"
else
echo " ⚠️ 警告: Soffice Service 容器已启动,但无法确认服务是否完全就绪"
echo " 请检查日志: docker logs rag-soffice"
fi
# 等待 ChromaDB 启动并检查连接
echo ""
echo "9. 等待 ChromaDB 启动并检查连接..."
sleep 3
# 检查 ChromaDB 是否正在运行
MAX_WAIT=30
WAIT_COUNT=0
CHROMA_READY=false
while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
if docker ps | grep -q "rag-chromadb.*Up"; then
# 尝试连接 ChromaDB检查映射的端口是否可访问
if command -v curl >/dev/null 2>&1; then
if curl -s -f "http://localhost:$CHROMA_PORT/api/v1/heartbeat" >/dev/null 2>&1 || \
curl -s -f "http://localhost:$CHROMA_PORT/api/v1/version" >/dev/null 2>&1; then
CHROMA_READY=true
break
fi
elif command -v nc >/dev/null 2>&1; then
if nc -z localhost $CHROMA_PORT 2>/dev/null; then
CHROMA_READY=true
break
fi
else
# 如果没有 curl 或 nc只检查容器是否运行
CHROMA_READY=true
break
fi
fi
echo " 等待 ChromaDB 启动... ($WAIT_COUNT/$MAX_WAIT 秒)"
sleep 2
WAIT_COUNT=$((WAIT_COUNT + 2))
done
if [ "$CHROMA_READY" = true ]; then
echo " ✓ ChromaDB 已就绪 (宿主机端口: $CHROMA_PORT)"
else
echo " ⚠️ 警告: ChromaDB 容器已启动,但无法确认服务是否完全就绪"
echo " 请检查日志: docker logs rag-chromadb"
fi
echo ""
echo "10. 启动 RAG API 容器..."
echo " 配置地址: $API_HOST:$API_PORT (从 .env 文件读取)"
# 停止并删除已存在的容器(如果存在)
docker stop rag-api 2>/dev/null || true
docker rm rag-api 2>/dev/null || true
# RAG API 使用 host 网络模式,以便直接访问宿主机上的 MySQL 和 Ollama
# ChromaDB 通过 localhost:$CHROMA_PORT 访问(因为 ChromaDB 使用端口映射)
# Soffice Service 通过 localhost:$SOFFICE_PORT 访问(因为 Soffice Service 使用端口映射)
docker run -d \
--name rag-api \
--network host \
--env-file .env \
-e API_HOST=$API_HOST \
-e API_PORT=$API_PORT \
-e CHROMA_SERVER_HOST=localhost \
-e CHROMA_SERVER_PORT=$CHROMA_PORT \
-e SOFFICE_PORT=$SOFFICE_PORT \
-v $(pwd)/logs:/app/logs \
-v $(pwd)/data:/app/data \
-v $(pwd)/static:/app/static \
-v $(pwd)/nltk_data:/app/nltk_data \
$DB_CONFIG_MOUNT \
--restart unless-stopped \
rag-rag-api:latest
echo " ✓ RAG API 容器已启动 (地址: $API_HOST:$API_PORT)"
echo ""
echo "=== 启动完成 ==="
echo ""
echo "服务状态:"
docker ps --filter "name=rag-" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "查看日志:"
echo " - RAG API: docker logs -f rag-api"
echo " - ChromaDB: docker logs -f rag-chromadb"
echo " - Soffice Service: docker logs -f rag-soffice"
echo ""
echo "访问服务:"
echo " - API 文档: http://localhost:$API_PORT/docs"
echo " - 健康检查: http://localhost:$API_PORT/health"
echo " - Soffice 健康检查: http://localhost:$SOFFICE_PORT/health"
echo ""
echo "端口配置:"
echo " - ChromaDB: $CHROMA_HOST:$CHROMA_PORT"
echo " - RAG API: $API_HOST:$API_PORT"
echo " - Soffice Service: localhost:$SOFFICE_PORT"
echo ""
echo "如果遇到端口占用错误,请:"
echo " 1. 检查端口占用: sudo lsof -i :$CHROMA_PORT 或 sudo lsof -i :$API_PORT 或 sudo lsof -i :$SOFFICE_PORT"
echo " 2. 停止占用端口的进程,或修改 .env 文件中的端口配置"