多容器Docker环境中React请求FastAPI遇net::ERR_NAME_NOT_RESOLVED错误
问题排查:Docker多容器中React请求无法解析容器域名
问题现象
- 搭建了包含
ui(Flask Web应用)和briefing(FastAPI应用)的多容器Docker系统 briefing容器内通过Python的requests库请求http://ui:8001/case-brief/api/upload/正常工作ui应用的React代码通过axios请求http://briefing:8000/process_assignment时,浏览器控制台返回net::ERR_NAME_NOT_RESOLVED错误,无HTTP状态码日志- 已尝试恢复初始代码、清除DNS缓存、改用fetch方法,问题未解决
原因分析
- 容器间的Python请求是在容器内部发起,Docker Compose默认创建的自定义网络支持通过服务名(如
ui/briefing)进行DNS解析,因此能正常通信 - React代码是在用户浏览器中运行,浏览器的DNS解析依赖本地网络环境,无法识别Docker Compose内部的服务域名,导致域名解析失败
解决办法
方案1:Flask反向代理(推荐,生产环境适用)
在ui的Flask服务中添加代理路由,将前端请求转发到briefing服务:
from flask import request, jsonify import requests # 在Flask app中添加代理路由 @app.route('/api/process_assignment', methods=['POST']) def proxy_to_briefing(): # 转发请求到briefing容器内部地址 briefing_url = 'http://briefing:8000/process_assignment' # 根据请求类型转发表单或文件数据 if request.files: response = requests.post(briefing_url, data=request.form, files=request.files) else: response = requests.post(briefing_url, json=request.get_json()) # 返回转发后的响应 return jsonify(response.json()), response.status_code
修改React代码中的请求地址为相对路径:
const response = await axios.post('/api/process_assignment', formData) .then(res => console.log(res.data)) .catch(err => console.error(err));
方案2:直接访问宿主机暴露的端口(开发环境快速验证)
修改React代码中的请求地址为宿主机IP+暴露的端口(briefing容器已映射8000端口到宿主机):
// 本地开发用localhost,远程部署用宿主机公网IP const response = await axios.post('http://localhost:8000/process_assignment', formData) .then(res => console.log(res.data)) .catch(err => console.error(err));
注意:生产环境不建议直接暴露服务端口,需配合反向代理或防火墙保障安全
相关配置代码
React请求代码(原问题代码)
const response = await axios.post('http://briefing:8000/process_assignment', formData) .then(res => console.log(res.data)) .catch(err => console.error(err));
Python请求代码(原问题代码)
response = requests.post('http://ui:8001/case-brief/api/upload/', json=test_json)
docker-compose.yml(原问题代码)
version: "3.8" services: briefing: build: context: ../app/briefing/ dockerfile: Dockerfile ports: - "8000:8000" volumes: - ../app/briefing:/app/ ui: build: context: ../app/ui/ dockerfile: Dockerfile ports: - "8001:8001" volumes: - ../app/ui:/app/ depends_on: - briefing
briefing容器Dockerfile(原问题代码)
# Pull base image FROM python:3.9.17-slim-bullseye # Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 COPY ./requirements.txt /app/requirements.txt RUN pip install -r /app/requirements.txt --no-cache-dir # Install dependencies RUN apt-get update && apt-get install -y wkhtmltopdf \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Set the path to the wkhtmltopdf executable as an environment variable ENV WKHTMLTOPDF_PATH /usr/bin/wkhtmltopdf RUN useradd -ms /bin/bash dockerfile_user USER dockerfile_user # Specify the FastAPI run command CMD ["sh", "-c", "cd /app && uvicorn main:app --host 0.0.0.0 --port 8000"]
ui容器Dockerfile(原问题代码)
# Use an official Python runtime as a parent image FROM python:3.8-slim-buster # Add the Flask app contents into the container at /app COPY ./requirements.txt /app/requirements.txt # Install any needed packages specified in requirements.txt RUN pip install -r /app/requirements.txt --no-cache-dir # CMD flask --app aira --debug run --host 0.0.0.0 --port 8001 CMD [ "sh", "-c", "cd /app && flask --app aira --debug run --host 0.0.0.0 --port 8001"]
内容的提问来源于stack exchange,提问作者spatel01
相关产品推荐
相关产品推荐

