PhysicsCorrection/docs/docker_deployment_guide.md

4.7 KiB
Raw Permalink Blame History

Docker 部署问题排查指南

问题描述

在 Docker 环境中部署工作流时,出现以下错误:

S3对象不存在: <!DOCTYPE HTML><html><head>...<title>404 Not Found</title>...

诊断步骤

1. 运行 URL 诊断脚本

在 Docker 容器内运行:

python scripts/test_urls.py

预期结果:所有 URL 应该显示 ✅ 有效

如果显示 ❌ 无效

  • 检查 Docker 容器网络配置
  • 检查 DNS 解析
  • 检查防火墙规则

2. 检查 Docker 网络配置

# 检查容器是否可以访问外网
docker exec <container_id> ping -c 3 8.8.8.8

# 检查 DNS 解析
docker exec <container_id> nslookup dpcclass.oss-cn-beijing.aliyuncs.com

# 检查是否能访问 OSS
docker exec <container_id> curl -I https://dpcclass.oss-cn-beijing.aliyuncs.com

3. 检查 LLM 服务网络

LLM 服务可能在隔离的网络环境中运行,无法直接访问外部 URL。

验证方法

  • 查看 LLM 服务的网络配置
  • 确认 LLM 服务可以访问外部 URL
  • 联系 LLM 服务提供商确认网络策略

解决方案

方案 1配置 Docker 网络使用宿主机网络

docker run --network host ...

优点

  • 容器使用宿主机的网络栈
  • 可以直接访问宿主机的网络资源

缺点

  • 端口可能冲突
  • 安全性降低

方案 2配置 DNS 解析

在 Dockerfile 中:

RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf

或在 docker-compose.yml 中:

services:
  app:
    dns:
      - 8.8.8.8
      - 114.114.114.114

方案 3添加 HTTP 代理

如果需要通过代理访问外网:

# 在容器内设置环境变量
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080

或在 Dockerfile 中:

ENV HTTP_PROXY=http://proxy.example.com:8080
ENV HTTPS_PROXY=http://proxy.example.com:8080

方案 4下载图片到本地推荐

如果 LLM 服务无法访问外部 URL可以在预处理阶段下载图片

import requests
import tempfile
import os
from pathlib import Path

def download_image_to_local(image_url: str) -> str:
    """
    下载图片到本地临时目录
    返回本地文件路径
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    
    response = requests.get(image_url, headers=headers, timeout=30)
    response.raise_for_status()
    
    # 保存到临时目录
    tmp_dir = Path("/tmp/homework_images")
    tmp_dir.mkdir(parents=True, exist_ok=True)
    
    # 生成文件名
    import hashlib
    filename = hashlib.md5(image_url.encode()).hexdigest() + ".jpg"
    local_path = tmp_dir / filename
    
    # 写入文件
    with open(local_path, "wb") as f:
        f.write(response.content)
    
    return str(local_path)

方案 5使用内网 OSS最佳

如果有内网 OSS可以

  1. 将图片从公网 OSS 复制到内网 OSS
  2. 使用内网 OSS URL
  3. 配置内网 OSS 访问权限

代码改进

我已经增强了 URL 验证逻辑:

1. 改进的图片 URL 验证(recognize_and_correct_node.py

# 检查 HTTP 状态码(只接受 200 和 206
if status_code not in (200, 206):
    raise ValueError(f"HTTP status code: {status_code}")

# 检查 Content-Type
content_type = response.headers.get('Content-Type', '')
if not content_type.startswith('image/'):
    logger.warning(f"Unexpected Content-Type: {content_type}")

# 检查是否为 HTML 错误页面
if b'<html' in preview_lower:
    # 提取具体错误信息404/403/500
    raise ValueError(f"URL returned HTML page ({error_msg})")

2. 改进的 Word 文档下载验证(doc_extract_node.py

# 验证 URL 格式
if not url.startswith(('http://', 'https://')):
    raise ValueError(f"Invalid URL format")

# 检查 HTTP 状态码
if status_code != 200:
    raise ValueError(f"HTTP Error {status_code}: {url}")

# 检查是否为有效的 docx
if not response.content.startswith(b'PK'):
    raise ValueError("Not a valid docx file")

临时解决方案

如果遇到无法解决的访问问题,可以:

1. 使用本地图片测试

{
  "student_homework": [
    {
      "student_id": 1,
      "student_name": "测试",
      "homework_images": ["file:///tmp/test_image.jpg"]
    }
  ],
  "answer_doc_url": ""
}

2. 禁用答案文档

{
  "answer_doc_url": "",
  ...
}

系统会自动切换到"专业老师批改模式",不依赖标准答案。

联系支持

如果以上方案都无法解决问题,请提供:

  1. Docker 容器网络配置
  2. python scripts/test_urls.py 的输出
  3. Docker 容器日志
  4. LLM 服务网络配置