使用Uvicorn在Docker容器部署Flet应用时遇错求助
在Docker中用Uvicorn运行Flet Web应用的问题排查
初始问题与错误
尝试在Docker容器中通过Uvicorn运行Flet Web应用时,遇到以下错误:
RuntimeError: asyncio.run() cannot be called from a running event loop 2024-05-27T18:46:46.450774857Z sys:1: RuntimeWarning: coroutine 'app_async' was never awaited
使用的启动代码:
def run_web(): ft.app(target=main, export_asgi_app=True)
入口启动脚本:
#!/usr/bin/env bash source .venv/bin/activate uvicorn --factory reggui.main:run_web --host 0.0.0.0 --port 8060
更新后的问题与错误
将main改为异步函数后,应用可以启动,但访问时出现500错误,日志如下:
INFO: Will watch for changes in these directories: ['/'] 2024-05-28T11:57:22.142940833Z INFO: Uvicorn running on http://0.0.0.0:8060 (Press CTRL+C to quit) 2024-05-28T11:57:22.142967464Z INFO: Started reloader process [8] using WatchFiles 2024-05-28T11:57:22.899964258Z WARNING: ASGI app factory detected. Using it, but please consider setting the --factory flag explicitly. 2024-05-28T11:57:22.900006979Z INFO: Started server process [10] 2024-05-28T11:57:22.900026356Z INFO: Waiting for application startup. 2024-05-28T11:57:22.900085509Z INFO: ASGI 'lifespan' protocol appears unsupported. 2024-05-28T11:57:22.900107430Z INFO: Application startup complete. 2024-05-28T11:57:53.724415871Z ERROR: Exception in ASGI application 2024-05-28T11:57:53.724433625Z Traceback (most recent call last): 2024-05-28T11:57:53.724436010Z File "/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 411, in run_asgi 2024-05-28T11:57:53.724438114Z result = await app( # type: ignore[func-returns-value] 2024-05-28T11:57:53.724439907Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.724441671Z File "/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 69, in __call__ 2024-05-28T11:57:53.724443514Z return await self.app(scope, receive, send) 2024-05-28T11:57:53.724445257Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.724447001Z File "/.venv/lib/python3.11/site-packages/uvicorn/middleware/asgi2.py", line 14, in __call__ 2024-05-28T11:57:53.724448804Z instance = self.app(scope) 2024-05-28T11:57:53.724450548Z ^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.724452281Z TypeError: 'NoneType' object is not callable 2024-05-28T11:57:53.724445979Z INFO: 172.20.0.1:34188 - "GET / HTTP/1.1" 500 Internal Server Error 2024-05-28T11:57:53.745830886Z ERROR: Exception in ASGI application 2024-05-28T11:57:53.745845213Z Traceback (most recent call last): 2024-05-28T11:57:53.745847708Z File "/.venv/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 411, in run_asgi 2024-05-28T11:57:53.745849792Z result = await app( # type: ignore[func-returns-value] 2024-05-28T11:57:53.745851786Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.745853689Z File "/.venv/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 69, in __call__ 2024-05-28T11:57:53.745852287Z INFO: 172.20.0.1:34198 - "GET /favicon.ico HTTP/1.1" 500 Internal Server Error 2024-05-28T11:57:53.745855603Z return await self.app(scope, receive, send) 2024-05-28T11:57:53.745871904Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.745874589Z File "/.venv/lib/python3.11/site-packages/uvicorn/middleware/asgi2.py", line 14, in __call__ 2024-05-28T11:57:53.745882965Z instance = self.app(scope) 2024-05-28T11:57:53.745884188Z ^^^^^^^^^^^^^^^ 2024-05-28T11:57:53.745885290Z TypeError: 'NoneType' object is not callable
问题原因与解决方案
1. 初始错误原因
当使用ft.app(target=main, export_asgi_app=True)时,Flet会返回一个ASGI应用对象,但你的run_web()函数没有返回这个对象。同时,如果main是同步函数,Flet内部会调用asyncio.run()启动应用,而Uvicorn本身已经在运行事件循环,导致冲突报错。
2. 更新后错误原因
将main改为异步函数解决了事件循环冲突,但run_web()仍然没有返回ASGI应用对象,Uvicorn拿到的是None,当尝试调用这个None对象时就会触发TypeError: 'NoneType' object is not callable。
3. 最终解决方案
修改run_web()函数,让它返回Flet生成的ASGI应用:
import flet as ft async def main(page: ft.Page): # 这里写你的应用逻辑 page.title = "我的Flet应用" await page.add_async(ft.Text("Hello, Flet!")) def run_web(): # 返回ASGI应用对象 return ft.app(target=main, export_asgi_app=True)
4. 额外优化建议
- Docker环境下如果不需要热重载,可以去掉Uvicorn的
--reload参数(如果之前加了),避免不必要的文件监听;如果需要热重载,指定具体的代码目录,比如--reload-dir ./reggui,防止监听根目录/带来的性能问题。 - 确保Dockerfile中正确设置了工作目录,比如
WORKDIR /app,并将代码复制到该目录下。 - 确认Docker容器的端口映射正确,比如
docker run -p 8060:8060 your-image。
内容的提问来源于stack exchange,提问作者fccoelho
相关产品推荐
相关产品推荐

