在我的 FastAPI 应用程序中,我安装了
static
目录来提供静态文件,如下所示:
app.mount('/static', StaticFiles(directory='static'), name='static')
FastAPI 应用程序从定义如下的 Docker 容器内部运行:
fhback:
container_name: fhback
build:
context: ./back
dockerfile: Dockerfile
restart: unless-stopped
expose:
- 8000
command: "gunicorn --workers 6 --timeout 60 --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker main:app"
volumes:
- ./back:/app
labels:
- traefik.enable=true
- traefik.http.routers.fhback.rule=Host(`example.com`) && PathPrefix(`/api`)
- traefik.http.routers.fhback.entrypoints=https
- traefik.http.routers.fhback.tls.certresolver=le
- traefik.http.middlewares.firehouse-compress.compress=true
- traefik.http.middlewares.fhback-stripprefix.stripprefix.prefixes=/api
- traefik.http.routers.fhback.middlewares=firehouse-compress,fhback-stripprefix
通过这些 Traefik 标签,我可以使用
https://example.com/api/docs
访问我的 Swagger,还可以使用 https://example.com/api/...
(外部)或 http://fhouse:8000/api/...
(本地,从 Docker)从前端调用 API 端点。
但我永远无法访问
static
目录中的静态文件!当我从 Docker 网络中的任何 Docker 容器执行 http://fhouse:8000/api/static/any-file.txt
时,它工作正常。但是当我尝试 https://example.com/api/static/any-file.txt
时,出现连接错误。我意识到我必须对 Traefik 配置做一些事情...有什么想法吗?
├── back
│ ├── Dockerfile
│ ├── main.py
│ ├── requirements.txt
│ └── static
│ └── test.html
└── docker-compose.yml
Traefik 和 API 都设置为服务。
🗎
docker-compose.yml
version: "3"
services:
traefik:
container_name: traefik
image: traefik:v2.5
command:
- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
fhback:
container_name: fhback
build:
context: ./back
dockerfile: Dockerfile
restart: unless-stopped
volumes:
- ./back:/app
labels:
- traefik.enable=true
- traefik.http.routers.fhback.rule=Host(`example.com`) && PathPrefix(`/`)
- traefik.http.services.fhback.loadbalancer.server.port=8000
- traefik.http.middlewares.firehouse-compress.compress=true
- traefik.http.routers.fhback.middlewares=firehouse-compress,fhback-stripprefix
- traefik.http.middlewares.testheader.headers.customresponseheaders.X-Test-Header=TraefikProxy
- traefik.http.routers.fhback.middlewares=testheader
depends_on:
- traefik
networks:
default:
external:
name: traefik
🗎
back/Dockerfile
FROM python:3.11.4-slim
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
WORKDIR /app
COPY . /app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
静态文件被直接烘焙到图像中。不过,您可以使用卷挂载从主机共享静态文件。
🗎
back/main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount('/static', StaticFiles(directory='static'), name='static')
@app.get("/")
async def root():
return {"message": "Hello World"}
🗎
requirements.txt
fastapi==0.109.2
uvicorn==0.27.1
测试:
curl -v --resolve example.com:80:127.0.0.1 http://example.com/static/test.html
我通过
docker-compose.yml
中的 Traefik 标签添加了响应标头。如果您查看下面的输出,您将看到该标头,确认响应来自 Traefik。您还可以在屏幕截图顶部面板的日志中看到它。