pythonnginxfastapi

FastAPI application with nginx - StaticFiles not working


I've a simple FastAPI project. It is running correctly in pycharm and in the docker container. When running via nginx, the StaticFiles are not delivered.

Structure is like this:

├── app
│   ├── main.py
│   ├── static_stuff
│   │   └── styles.css
│   └── templates
│       └── item.html
├── Dockerfile
├── requirements.txt

main.py

from fastapi import Request, FastAPI
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import os.path as path


ROOT_PATH =  path.abspath(path.join(__file__ ,"../"))

app = FastAPI(title="my_app", root_path='/my_app')
app.mount("/static_stuff", StaticFiles(directory=f"/{ROOT_PATH}/static_stuff"), name="static")
templates = Jinja2Templates(directory=f"/{ROOT_PATH}/templates")


@app.get("/items/{id}", response_class=HTMLResponse, include_in_schema=False)
async def read_item(request: Request, id: str):
    return templates.TemplateResponse(
        request=request, name="item.html", context={"id": id}
    )

The application is running in a docker container:

Dockerfile:

FROM python:3.13-slim
WORKDIR /my_app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
CMD ["gunicorn",  "-k",  "uvicorn.workers.UvicornWorker", "app.main:app", "--bind",  "0.0.0.0:6543"]

EXPOSE 6543

The nginx configuration looks like this:

location /my_app {
    proxy_pass        http://my_host:6543;
    include           proxy_params;
}

When calling the nginx -> http://my_host/my_app/items/5

Everything works except the staticfiles. The styles.css is not found. What am I doing wrong?

I tried something like this, but I had no success

location ~ /static_stuff/(.+) {
    proxy_pass        http://my_host:6543;
    include           proxy_params;
}

Solution

  • It seems like there is a bug in FastAPI with root_path parameter for mounted paths. If you specify root_path as a parameter of __init__ it expects additional my_app/ in path. So, your files are available on /my_app/my_app/static_stuff/ instead of /my_app/static_stuff/.

    Try specifying root_path as an argument of server (e.g. uvicorn main:app --root-path my_app for uvicorn) instead of passing it as a parameter of __init__.