You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose中FastAPI微服务无法通信问题求助

容器化服务间REST通信失败问题排查

问题描述

我有两个需要通过REST通信的服务:predict和preprocess。本地通过以下curl命令可以正常调用preprocess服务:

curl -X 'POST' \
  'http://0.0.0.0:3000/preprocess' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "feature_1": 1,
  "feature_2": 2
}'

但将两个服务容器化后,在predict服务内部调用preprocess服务时失败,错误信息如下:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='0.0.0.0', port=3000): Max retries exceeded with url: /preprocess (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fb53b37ad70>: Failed to establish a new connection: [Errno 111] Connection refused'))

项目结构如下:

项目:
├── predict_service
│   ├── main.py
│   ├── requirements.txt
│   └── Dockerfile
├── preprocess_service
│   ├── main.py
│   ├── requirements.txt
│   └── Dockerfile
└── docker-compose.yml

相关配置文件

predict_service的Dockerfile

FROM python:3.10

WORKDIR /app 

COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

preprocess_service的Dockerfile

FROM python:3.10

WORKDIR /app 

COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY . .

EXPOSE 3000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

docker-compose.yml

version: "3"
services:
  predict_service:
    image: dockerplaygroundpredict:latest
    command: uvicorn main:app --host 0.0.0.0 
    ports:
      - "8000:8000"
  preprocess_service:
    image: dockerplaygroundpreprocess:latest
    command: uvicorn main:app --host 0.0.0.0
    ports:
      - "3000:8000"

predict_service的main.py核心代码

app = FastAPI(
    title="SIMPLE FASTAPI POC",
    description="----> PREDICTION",
    version="0.1"
)

@app.get("/")
def read_root():
    """Health check."""
    return {"message": HTTPStatus.OK.phrase, "status-code": HTTPStatus.OK,}

@app.post("/predict", tags=["Prediction"])
def predict(request: Request, sample: FeatureSample) -> Dict:
    """Predict output for sample input."""
    headers = {
        'accept': 'application/json',
    }
    json_data = {
        'feature_1': 1,
        'feature_2': 2,
    }
    preprocessing_response = requests.post('http://0.0.0.0:3000/preprocess', 
                                           headers=headers, json=json_data)
    return {"message": HTTPStatus.OK.phrase, "status-code": HTTPStatus.OK, "data": {"predictions": "Dummy_Prediction"}}

错误原因分析

  1. 容器间调用地址错误:
    在predict服务的代码中,使用http://0.0.0.0:3000/preprocess发起请求,但容器内的0.0.0.0指向当前predict容器自身,而非宿主机的3000端口。在Docker Compose创建的默认网络中,服务之间需要通过服务名称(而非IP或0.0.0.0)作为主机名来通信。

  2. 端口配置不一致:

    • preprocess服务的Dockerfile中EXPOSE 3000,但启动命令未指定端口,uvicorn默认运行在8000端口,导致声明暴露的端口与实际运行端口不符。
    • docker-compose.yml中preprocess的端口映射为3000:8000(宿主机3000映射到容器8000),本地curl能正常访问是因为走了宿主机端口,但容器内部调用需要使用容器内的实际服务端口8000,而非宿主机的3000端口。

修复步骤

步骤1:修正predict服务的调用地址

修改predict_service/main.py中的请求地址,将http://0.0.0.0:3000/preprocess替换为http://preprocess_service:8000/preprocess(preprocess_service是docker-compose.yml中定义的服务名称,8000是preprocess容器内服务的实际运行端口):

preprocessing_response = requests.post('http://preprocess_service:8000/preprocess', 
                                       headers=headers, json=json_data)

步骤2:统一preprocess服务的端口配置(可选但推荐)

为了避免端口混淆,建议让preprocess服务的声明端口与实际运行端口一致:

  • 修改preprocess_service/Dockerfile的启动命令,指定端口为3000:
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"]
    
  • 同步修改docker-compose.yml中preprocess的端口映射:
    preprocess_service:
      image: dockerplaygroundpreprocess:latest
      command: uvicorn main:app --host 0.0.0.0 --port 3000
      ports:
        - "3000:3000"
    
    此时predict服务的调用地址也需要同步改为http://preprocess_service:3000/preprocess。

步骤3:重启服务

执行以下命令重新构建镜像并启动容器:

docker-compose down
docker-compose build
docker-compose up -d

内容的提问来源于stack exchange,提问作者Joe Dawson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:51:26