#!/bin/bash # 容器启动脚本:安装依赖 + 环境修复 + 启动 web_server。 # compose 的 python-app 服务 command 指向本脚本。 # # 为什么需要环境修复(必须在 pip install 之后): # rapidocr_onnxruntime 的依赖声明是 opencv-python(GUI 版),pip 解析依赖时 # 会强制装回它;而 GUI 版依赖 X11 库(libxcb),python:slim 容器里 import cv2 # 直接崩溃 → RapidOCR 不可用 → 条件判断的 OCR 步骤抛异常 → 任务失败退出。 # 因此在安装完 requirements 后,最后强制卸载 GUI 版并装 headless(幂等)。 # 本地 Mac 有 GUI 环境不受影响。 if [ -f requirements.txt ]; then pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt fi # 环境修复:最后强制 headless(覆盖 rapidocr 拉回的 GUI 版) pip uninstall -y -q opencv-python 2>/dev/null || true pip install -q -i https://pypi.tuna.tsinghua.edu.cn/simple "opencv-python-headless>=4.8,<5" # 5.x wheel 无 cv2 模块,锁定 4.x # pip 24.0 解压 abi3 wheel 偶发丢根文件(4.14.0.94 实测 site-packages/cv2 只剩子目录, # cv2.abi3.so / __init__.py 缺失 → import cv2 成空壳,OCR 全挂)→ 空壳检测 + wheel 手动解压兜底(幂等) python3 - <<'PY' import glob, os, shutil, site, subprocess, sys, zipfile def cv2_ok(): try: import cv2 return hasattr(cv2, "__version__") and cv2.__file__ is not None except Exception: return False if cv2_ok(): sys.exit(0) print("cv2 空壳,wheel 手动解压修复...") r = subprocess.run(["pip", "download", "--no-deps", "-q", "-i", "https://pypi.tuna.tsinghua.edu.cn/simple", "-d", "/tmp/ocv", "opencv-python-headless>=4.8,<5"], capture_output=True) if r.returncode != 0: sys.exit(1) w = sorted(glob.glob("/tmp/ocv/opencv_python_headless*.whl"))[-1] with zipfile.ZipFile(w) as z: z.extractall("/tmp/ocv") dst = os.path.join(site.getsitepackages()[0], "cv2") shutil.rmtree(dst, ignore_errors=True) shutil.copytree("/tmp/ocv/cv2", dst) import cv2 print(f"cv2 {cv2.__version__} 手动解压修复完成") PY # 启动 MCP server(后台,AI 控制台/外部客户端经 127.0.0.1:8033 调用)。 # web_server.py 内 agent 依赖它,容器重启必须自动拉起(MCP_ENABLED=0 可关)。 # 平台账号:MCP_PLATFORM_USER 默认 admin;密码优先取环境变量(compose/.env), # 兜底 admin123 与部署时的手动启动参数一致。 if [ -f mcp_server/mcp_server.py ] && [ "${MCP_ENABLED:-1}" = "1" ]; then echo "[start] 启动 MCP server..." MCP_ALLOW_WRITE=1 \ MCP_PLATFORM_USER="${MCP_PLATFORM_USER:-admin}" \ MCP_PLATFORM_PASS="${MCP_PLATFORM_PASS:-admin123}" \ MCP_AUDIT_FILE="${MCP_AUDIT_FILE:-/tmp/mcp_audit.log}" \ python3 -m mcp_server.mcp_server > /tmp/mcp_server.log 2>&1 & fi exec python -u web_server.py