FastAPI lifespan在Docker中以uv run -m方式运行时不生效的问题咨询
FastAPI lifespan在Docker中以uv run -m方式运行时不生效的问题咨询
我来帮你分析这个问题的原因和对应的解决办法:
问题场景梳理
你已经在retrofun/api.py中定义了带lifespan上下文管理器的FastAPI应用,然后在__main__.py中通过命令行参数启动服务。本地用python -m retrofun启动时lifespan正常工作,但Docker中用uv run -m retrofun启动时,lifespan的日志完全没输出,换成fastapi run的方式又能恢复正常。
问题根源分析
问题出在**uvicorn.run的启动参数**和reload=True的组合上:
- 你当前在
__main__.py中用模块路径字符串"retrofun.__main__:app_api"指定要运行的应用,同时开启了reload=True。 - 当在Docker中用
uv run -m retrofun启动时,uv run的模块加载机制和uvicorn的reload模式发生了冲突:uvicorn会启动子进程重新加载指定的模块路径,而在二次加载过程中,app_api的lifespan上下文管理器因为模块导入的上下文变化,没有被正确绑定和执行。 - 而
Case3中fastapi run的方式是直接加载指定文件并获取已初始化的app_api对象,绕开了模块路径字符串的二次加载问题,所以lifespan能正常执行。
本地python -m retrofun正常是因为本地环境的模块加载路径和Docker中uv run的环境存在细微差异,没有触发这个加载冲突。
解决办法
修改__main__.py中uvicorn.run的调用方式,直接传入已初始化的app_api对象,而非模块路径字符串,这样uvicorn会直接使用现成的应用实例,避免二次加载模块导致的问题:
# 修改后的uvicorn.run代码 uvicorn.run( app_api, # 替换原模块路径字符串为直接传入app对象 host=host, port=port, reload=True )
修改后,不管是本地python -m retrofun、Docker中uv run -m retrofun还是其他启动方式,lifespan都会正常执行并输出日志。
额外建议
生产环境建议关闭reload=True(该模式仅用于开发热重载),如果Docker开发时需要热重载,可以通过挂载本地代码目录的方式实现,避免uvicorn的reload模式带来的模块加载问题。
备注:内容来源于stack exchange,提问作者HieuHIenHoa
相关产品推荐
相关产品推荐

