FastAPI双端口部署问题:metrics服务无法访问如何解决?
解决第二个FastAPI实例无法访问的问题
问题根源
你在Docker命令里用&后台启动第二个uvicorn进程,Docker容器默认只监控PID为1的进程,后台运行的第二个进程可能未被正确维持,或者启动时出现异常未被捕获。另外也需确认代码里的metrics_app是否正确初始化。
具体修复方案
方案1:用启动脚本替代命令拼接
在src目录下创建启动脚本start.sh:
#!/bin/bash uvicorn app.main:app --reload --workers 1 --host 0.0.0.0 --port 8000 & pid1=$! uvicorn app.main:app2 --reload --workers 1 --host 0.0.0.0 --port 8001 & pid2=$! # 等待任意进程退出,维持容器存活 wait $pid1 $pid2
给脚本添加执行权限:
chmod +x start.sh
修改docker-compose.yml里的command字段:
command: ./start.sh
容器会以脚本作为PID 1进程,同时维持两个uvicorn实例运行。
方案2:检查metrics_app的定义
确保metrics_app是正确的ASGI应用,比如使用prometheus-fastapi-instrumentator时,初始化代码应类似:
from prometheus_fastapi_instrumentator import Instrumentator # 若为主app生成metrics,挂载到app2 Instrumentator().instrument(app).expose(app2, endpoint="/metrics", include_in_schema=False)
或单独创建ASGI应用挂载:
from fastapi import FastAPI from starlette_prometheus import metrics, PrometheusMiddleware metrics_app = FastAPI() metrics_app.add_middleware(PrometheusMiddleware) metrics_app.add_route("/metrics", metrics)
如果metrics_app未正确初始化,即使挂载到app2,访问/metrics也会报错。
方案3:验证容器内端口监听状态
进入容器内部,检查8001端口是否被uvicorn进程监听:
docker exec -it <容器ID> /bin/bash netstat -tulpn | grep 8001
若未监听,查看容器日志排查启动错误:
docker logs <容器ID>
常见错误包括模块导入失败、端口占用等。
方案4:临时移除--reload测试
--reload模式下uvicorn会启动子进程,可能与后台运行方式冲突,测试时可暂时去掉该参数:
command: uvicorn app.main:app --workers 1 --host 0.0.0.0 --port 8000 & uvicorn app.main:app2 --workers 1 --host 0.0.0.0 --port 8001
额外建议
若仅需限制/metrics接口的访问,无需创建第二个FastAPI实例——直接在主app挂载metrics,然后通过Docker网络配置限制8001端口仅对内网开放(不将该端口映射到宿主机公网),让监控服务在同一Docker网络内访问容器的8001端口即可,这种方式更简洁。
内容的提问来源于stack exchange,提问作者tobias
相关产品推荐
相关产品推荐

