You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器中FastAPI用Uvicorn+WatchFiles自动重载失效问题

问题

开发FastAPI应用时,通过docker-compose在Docker容器中运行Uvicorn,开发阶段希望除*.py文件外,其他类型文件变更也能触发自动重载。根据Uvicorn文档,需安装可选依赖WatchFiles才能使用--reload-include参数,但安装后Uvicorn启动时虽提示使用WatchFiles,却完全不触发任何自动重载(无论是否使用include参数);未安装WatchFiles时,Uvicorn默认仅对*.py文件的自动重载正常工作。

现有配置:

Dockerfile

FROM python:3.10

WORKDIR /tmp

RUN pip install --upgrade pip

COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade -r requirements.txt

WORKDIR /code

CMD ["uvicorn", "package.main:app", "--host", "0.0.0.0", "--port", "80", "--reload"]

docker-compose.yml

version: "3.9"

services:
  fastapi-dev:
    image: myimagename:${TAG:-latest}
    build:
      context: .
    volumes:
      - ./src:/code
      - ./static:/static
      - ./templates:/templates
    restart: on-failure
    ports:
      - "${HTTP_PORT:-8080}:80"

已尝试操作:

  • 在docker-compose.yml中替换Dockerfile的CMD命令,无变化
  • 编写watch.py测试WatchFiles,确认其在容器中可正常检测文件变更,排除文件系统挂载问题

需求:修复该问题,或提供其他实现多类型文件触发重载的方法;若需修复WatchFiles,给出具体步骤。

解决方法

一、修复WatchFiles配合Uvicorn的自动重载问题

  1. 明确指定监听路径
    Uvicorn默认仅监听工作目录(/code)下的文件,你的static和templates目录挂载在容器的/static和/templates,不在默认监听范围内。需要用--reload-dir参数指定这些额外路径,结合--reload-include设置要监听的文件类型。

    修改Dockerfile的CMD或docker-compose的command:

    uvicorn package.main:app --host 0.0.0.0 --port 80 --reload --reload-dir /code --reload-dir /static --reload-dir /templates --reload-include "*.html" --reload-include "*.css" --reload-include "*.js"
    

    可根据需求调整--reload-include的文件类型。

  2. 确认版本兼容性
    检查requirements.txt中WatchFiles与Uvicorn的版本匹配度,比如Uvicorn 0.24.x推荐搭配WatchFiles 0.19+,避免版本不兼容导致监听失效。在requirements.txt中明确指定:

    uvicorn>=0.24.0
    watchfiles>=0.19.0
    
  3. 添加重载延迟
    部分Docker环境下文件系统挂载存在缓存,导致WatchFiles无法及时检测变更。可在启动Uvicorn时添加--reload-delay 1参数,给文件系统同步留缓冲时间:

    uvicorn ... --reload --reload-delay 1 ...
    

二、替代方案:无需WatchFiles实现多类型文件重载

如果WatchFiles的问题暂时无法解决,可尝试以下两种方式:

  1. 自定义文件监听重启脚本
    编写Python脚本,用WatchFiles监听目标文件变更,一旦检测到变化就重启Uvicorn进程。示例脚本:

    import subprocess
    from watchfiles import watch
    
    def restart_uvicorn():
        subprocess.run(["pkill", "-f", "uvicorn"], check=False)
        subprocess.Popen(["uvicorn", "package.main:app", "--host", "0.0.0.0", "--port", "80"])
    
    if __name__ == "__main__":
        restart_uvicorn()
        for changes in watch("/code", "/static", "/templates"):
            print(f"Detected changes: {changes}")
            restart_uvicorn()
    

    修改Dockerfile的CMD为启动该脚本:

    CMD ["python", "/code/watch_restart.py"]
    
  2. 启用模板自动重载
    针对Jinja2模板文件,可直接启用其自身的自动重载功能,无需Uvicorn重启。在FastAPI中配置:

    from fastapi import FastAPI
    from fastapi.templating import Jinja2Templates
    
    app = FastAPI()
    templates = Jinja2Templates(directory="/templates")
    templates.env.auto_reload = True
    templates.env.cache = {}
    

    静态资源(CSS/JS)可通过浏览器禁用缓存实现开发阶段实时更新,或配合上述自定义脚本监听。

内容的提问来源于stack exchange,提问作者Even0900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:55:24