361 lines
12 KiB
Bash
361 lines
12 KiB
Bash
#!/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 文件中的端口配置"
|
||
|