Uvicorn --reload 使用 WatchFiles 不适用于 Docker 容器中的 FastAPI

Eve*_*900 7 python docker docker-compose fastapi uvicorn

我正在开发一个 FastAPI 应用程序。它使用 docker-compose 在 Docker 容器中的 Uvicorn 上运行。

\n

我想包含一些文件,而不是*.py在开发过程中触发自动重新加载。

\n

根据文档, Uvicorn 需要安装可选的依赖项 WatchFiles 才能使用该--reload-include标志,这将使我能够包含其他文件类型来触发重新加载。但是,当安装 WatchFiles 时(Uvicorn 通过在启动时打印此信息来确认:)Started reloader process [1] using WatchFiles根本不会发生自动重新加载。请注意,这与运行命令的更改无关,无论是否包含包含标志。

\n

如果没有安装 WatchFiles,Uvicorn 的默认自动重新加载功能仅适用于*.py文件。

\n

我有什么

\n

这是 Dockerfile:

\n
FROM python:3.10\n\nWORKDIR /tmp\n\nRUN pip install --upgrade pip\n\nCOPY requirements.txt .\nRUN pip install --no-cache-dir --upgrade -r requirements.txt\n\nWORKDIR /code\n\nCMD ["uvicorn", "package.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]\n
Run Code Online (Sandbox Code Playgroud)\n

这是 docker-compose.yml:

\n
FROM python:3.10\n\nWORKDIR /tmp\n\nRUN pip install --upgrade pip\n\nCOPY requirements.txt .\nRUN pip install --no-cache-dir --upgrade -r requirements.txt\n\nWORKDIR /code\n\nCMD ["uvicorn", "package.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]\n
Run Code Online (Sandbox Code Playgroud)\n

(我需要一个 docker-compose 文件,因为稍后需要一些服务。)

\n

最基本的 FastAPI 应用程序:

\n
version: "3.9"\n\nservices:\n  fastapi-dev:\n    image: myimagename:${TAG:-latest}\n    build:\n      context: .\n    volumes:\n      - ./src:/code\n      - ./static:/static\n      - ./templates:/templates\n    restart: on-failure\n    ports:\n      - "${HTTP_PORT:-8080}:80"\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,这可能并不重要,因为该问题似乎与 FastAPI 无关。

\n

要求.txt:

\n
fastapi~=0.85\npydantic[email]~=1.10.2\nvalidators~=0.20.0\nuvicorn~=0.18\nwatchfiles\npython-decouple==3.6\npython-multipart\npyotp~=2.7\nwheezy.template~=3.1\n
Run Code Online (Sandbox Code Playgroud)\n

我如何尝试解决这个问题?

\n

我尝试command: uvicorn package.main:app --host 0.0.0.0 --port 80 --reload在 docker-compose.yml 中使用而不是CMD [...]在 Dockerfile 中使用,这毫不奇怪地没有改变任何内容。

\n

我创建了一个文件watch.py来测试 WatchFiles 是否有效:

\n
from fastapi import FastAPI, HTTPException\n\napp = FastAPI()\n\n\n@app.get(\'/\')\nasync def index():\n    raise HTTPException(418)\n\n
Run Code Online (Sandbox Code Playgroud)\n

而\xe2\x80\xa6事实上它确实有效。从 Docker CLI 中的容器运行它会打印所做的所有更改。( python -m watch) 顺便说一句,它的工作原理与异步/使用 asyncio 一样好。所以这可能与 Docker 内的文件系统/共享/挂载无关。

\n

所以\xe2\x80\xa6

\n

我如何解决它?Uvicorn(?) 有什么问题吗?我需要检查其他文件类型,*.html例如/templates. 我必须让 WatchFiles 才能工作还是还有其他方法?如果我这样做,怎么办?

\n

Ast*_*lot 4

我刚刚遇到了同样的问题,问题出在 WatchFiles 上。

watchfiles 文档中,据了解,检测依赖于文件系统通知,并且我认为通过 docker 在使用卷时不会启动其事件。

如果无法使用文件系统通知,Notify 将回退到文件轮询

所以你必须告诉监视文件强制轮询,这就是你在测试 python 脚本中使用参数所做的事情force_polling,这就是它起作用的原因:

for changes in watch('/code', force_polling=True):
Run Code Online (Sandbox Code Playgroud)

幸运的是,在文档中,我们可以通过环境变量强制轮询。将此环境变量添加到您的环境变量中docker-compose.yml,自动重新加载将起作用:

services:
  fastapi-dev:
    image: myimagename:${TAG:-latest}
    build:
      context: .
    volumes:
      - ./src:/code
      - ./static:/static
      - ./templates:/templates
    restart: on-failure
    ports:
      - "${HTTP_PORT:-8080}:80"
    environment:
      - WATCHFILES_FORCE_POLLING=true
Run Code Online (Sandbox Code Playgroud)

  • 我也在使用最新版本的FastAPI,但仍然有问题,也许它也与Docker版本有关,不知道!不管怎样,我为你感到高兴,一切都恢复正常了! (3认同)