# Docker 部署问题排查指南
## 问题描述
在 Docker 环境中部署工作流时,出现以下错误:
```
S3对象不存在:
...404 Not Found...
```
## 诊断步骤
### 1. 运行 URL 诊断脚本
在 Docker 容器内运行:
```bash
python scripts/test_urls.py
```
**预期结果**:所有 URL 应该显示 `✅ 有效`
**如果显示 `❌ 无效`**:
- 检查 Docker 容器网络配置
- 检查 DNS 解析
- 检查防火墙规则
### 2. 检查 Docker 网络配置
```bash
# 检查容器是否可以访问外网
docker exec ping -c 3 8.8.8.8
# 检查 DNS 解析
docker exec nslookup dpcclass.oss-cn-beijing.aliyuncs.com
# 检查是否能访问 OSS
docker exec curl -I https://dpcclass.oss-cn-beijing.aliyuncs.com
```
### 3. 检查 LLM 服务网络
LLM 服务可能在隔离的网络环境中运行,无法直接访问外部 URL。
**验证方法**:
- 查看 LLM 服务的网络配置
- 确认 LLM 服务可以访问外部 URL
- 联系 LLM 服务提供商确认网络策略
## 解决方案
### 方案 1:配置 Docker 网络使用宿主机网络
```bash
docker run --network host ...
```
**优点**:
- 容器使用宿主机的网络栈
- 可以直接访问宿主机的网络资源
**缺点**:
- 端口可能冲突
- 安全性降低
### 方案 2:配置 DNS 解析
在 Dockerfile 中:
```dockerfile
RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf
```
或在 docker-compose.yml 中:
```yaml
services:
app:
dns:
- 8.8.8.8
- 114.114.114.114
```
### 方案 3:添加 HTTP 代理
如果需要通过代理访问外网:
```bash
# 在容器内设置环境变量
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
```
或在 Dockerfile 中:
```dockerfile
ENV HTTP_PROXY=http://proxy.example.com:8080
ENV HTTPS_PROXY=http://proxy.example.com:8080
```
### 方案 4:下载图片到本地(推荐)
如果 LLM 服务无法访问外部 URL,可以在预处理阶段下载图片:
```python
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`)
```python
# 检查 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'