Firecrawl 部署实战:端口冲突故障排查与解决全记录

终极 改写 发布于 2025-10-04 205 次阅读


最近弄了好多东西,根本没有时间记录,所以用 AI(DeepSeek) 记录总结一次完整的 Firecrawl 容器化部署故障排查过程,详细记录从问题发现到解决的每一步。不得不说 DeepSeek 最新的 3.2 模型真的垃圾,写个记录总结都做不好,丢三落四的简直就是老人痴呆,没时间人工修正,凑合着看吧。顺便提一嘴,还是今年5月份的 Google Gemini 2.5 Pro 才是真强,是至今唯一让我感觉惊艳的模型,能力真的强太多了,很多时候我都不用说太多讲太明白,它就能 Get 到了,智商很高,现在的都是些降智的智障货色,要写一大堆提示,还做不好。

另外吐槽一下 Firecrawl 官方的部署说明(firecrawl/SELF_HOST.md at main · firecrawl/firecrawl),按照它的步骤操作根本不行,必须修改官方的 .env 和 docker-compose.yml 文件才能部署成功。

问题初现:服务无法访问

在部署 Firecrawl 项目后,发现 API 服务无法正常启动:

sudo docker compose logs api

关键错误信息:

Error: listen EADDRINUSE: address already in use 0.0.0.0:3002
api Node.js v22.20.0
✗ api 13.8s (1)
✗ Fatal error occurred

第一步:确认问题现象

1.1 检查服务状态

sudo docker compose ps

发现只有基础服务运行,API 服务反复重启。

1.2 查看详细日志

sudo docker compose logs api --tail=50

发现服务在启动过程中多次尝试绑定 3002 端口失败。

第二步:分析端口占用情况

2.1 检查宿主机端口占用

sudo lsof -i :3002
sudo netstat -tulpn | grep 3002

确认 3002 端口是否被其他进程占用。

2.2 检查 Docker 容器端口映射

sudo docker ps -a --format "table {{.Names}}\t{{.Ports}}"

查看所有容器的端口映射情况。

第三步:深入分析服务架构

3.1 分析 docker-compose.yml 结构

services:
  api:
    ports:
      - "3002:3002"  # 外部:内部端口映射
    environment:
      PORT: 3002     # 容器内部服务端口
      
  playwright-service:
    environment:
      PORT: 3000     # 内部使用3000端口
      
  extract-worker:
    # 官方配置文件中根本就没有这个,健康检查默认使用3002端口

3.2 发现关键问题

通过分析发现多个服务存在端口冲突:

  • api 服务:内部使用 3002 端口
  • extract-worker:健康检查也使用 3002 端口
  • playwright-service:使用 3000 端口(可能与宿主机其他服务冲突)

第四步:制定解决方案

4.1 端口重新规划方案

服务                原端口   新端口
------             ------   ------
api (内部)          3002     3004
api (外部映射)      3002:3002  3002:3004
playwright-service  3000     3001
extract-worker      3002     3003

4.2 修改配置文件

更新 .env 文件:

# 端口配置
PORT=3002          # 外部访问端口
INTERNAL_PORT=3004 # 新增API容器内部端口
HOST=0.0.0.0

# 服务配置
PLAYWRIGHT_MICROSERVICE_URL=http://playwright-service:3001/scrape

更新 docker-compose.yml:

services:
  api:
    environment:
      PORT: ${INTERNAL_PORT:-3004}  # 改为3004
      WORKER_PORT: ${WORKER_PORT:-3005}
      EXTRACT_WORKER_PORT: ${EXTRACT_WORKER_PORT:-3003}  # 新增
    ports:
      - "${PORT:-3002}:${INTERNAL_PORT:-3004}"  # 外部3002映射到内部3004

  playwright-service:
    environment:
      PORT: 3001  # 改为3001避免冲突
    ports:
      - "3001:3001"

第五步:实施解决方案

5.1 停止现有服务

sudo docker compose down

5.2 清理环境

# 检查并释放可能被占用的端口
sudo lsof -i :3003
sudo lsof -i :3004

5.3 应用新配置

# 重新启动服务
sudo docker compose up -d

第六步:验证解决方案

6.1 检查服务状态

sudo docker compose ps

期望输出:所有服务状态为 "Up"

6.2 验证端口映射

sudo docker port firecrawl-api-1

确认端口正确映射:3004/tcp -> 0.0.0.0:3002

6.3 测试服务健康状态

# 测试playwright-service
curl http://localhost:3001/health

# 测试API服务
curl http://localhost:3002/

# 测试API功能
curl -X POST http://localhost:3002/v0/scrape \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com"]}'

6.4 检查服务日志

sudo docker compose logs api --tail=20
sudo docker compose logs playwright-service --tail=10

确认无错误信息,服务正常启动。

第七步:配置不必需的环境变量

7.1 设置AI功能所需变量

# 编辑.env文件添加配置
echo 'OPENAI_API_KEY=your_actual_api_key_here' >> .env
echo 'MODEL_NAME=gpt-3.5-turbo' >> .env
echo 'MODEL_EMBEDDING_NAME=text-embedding-3-small' >> .env

7.2 重启服务应用配置

sudo docker compose down
sudo docker compose up -d

最终验证

完整功能测试

# 1. 检查所有服务状态
sudo docker compose ps

# 2. 测试各服务端点
curl -s http://localhost:3001/health | jq '.status'
curl -s http://localhost:3002/v0/ | jq '.'

# 3. 执行完整爬取测试
curl -X POST http://localhost:3002/v0/scrape \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TEST_API_KEY}" \
  -d '{
    "urls": ["https://httpbin.org/json"],
    "formats": ["markdown"]
  }' | jq '.'

排查总结

通过这次故障排查,总结出容器化部署的排查要点:

  1. 从现象到根源:从服务重启现象追溯到端口冲突根本原因
  2. 系统化分析:逐层分析宿主机、Docker、容器内部的端口使用情况
  3. 架构理解:深入理解微服务架构中各组件的交互关系
  4. 渐进式解决:小步修改、及时验证,确保每一步改动都有效

这次排查不仅解决了当前的端口冲突问题,更重要的是建立了一套完整的 Docker 容器故障排查方法论,为后续的运维工作奠定了坚实基础。