From 43c33bb714c971ce0e88b959a6dca0b3f1700691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Gruszczy=C5=84ski?= Date: Wed, 15 Jul 2026 08:51:57 +0200 Subject: [PATCH] favicon --- Dockerfile | 24 +++++++++++++++++------- app/main.py | 8 ++++---- app/static/favicon.ico | Bin 0 -> 15406 bytes requirements.txt | 12 ++++++------ 4 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 app/static/favicon.ico diff --git a/Dockerfile b/Dockerfile index 392cb47..a1af301 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,29 @@ -FROM python:3.13-slim +FROM python:3.14-alpine ENV PYTHONDONTWRITEBYTECODE=1 \ - PYTHONUNBUFFERED=1 + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 WORKDIR /app -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential curl \ - && rm -rf /var/lib/apt/lists/* +RUN apk add --no-cache \ + curl \ + freetype \ + libjpeg-turbo \ + zlib \ + && apk add --no-cache --virtual .build-deps \ + build-base \ + freetype-dev \ + libffi-dev \ + libjpeg-turbo-dev \ + zlib-dev COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install -r requirements.txt \ + && apk del .build-deps COPY app ./app RUN mkdir -p /app/exports -EXPOSE 8000 +EXPOSE 8147 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8147"] diff --git a/app/main.py b/app/main.py index ce5c191..42601c4 100644 --- a/app/main.py +++ b/app/main.py @@ -12,7 +12,7 @@ import httpx from io import BytesIO from bs4 import BeautifulSoup from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Response -from fastapi.responses import HTMLResponse, StreamingResponse, JSONResponse +from fastapi.responses import FileResponse, HTMLResponse, StreamingResponse, JSONResponse from fastapi.staticfiles import StaticFiles from reportlab.lib import colors from reportlab.lib.pagesizes import A4, landscape @@ -68,9 +68,9 @@ async def no_cache_headers(request, call_next): return response -@app.get("/favicon.ico") -def favicon() -> Response: - return Response(status_code=204) +@app.get("/favicon.ico", include_in_schema=False) +def favicon() -> FileResponse: + return FileResponse(BASE_DIR / "static" / "favicon.ico", media_type="image/x-icon") @app.get("/", response_class=HTMLResponse) diff --git a/app/static/favicon.ico b/app/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..332bbea5d9b2504531bb9e50554d5a6837c22ef3 GIT binary patch literal 15406 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.115.6 +uvicorn[standard]>=0.34.0 pydantic>=2.10.4 -httpx==0.28.1 -beautifulsoup4==4.12.3 -reportlab==4.2.5 -python-multipart==0.0.20 +httpx>=0.28.1 +beautifulsoup4>=4.12.3 +reportlab>=4.2.5 +python-multipart>=0.0.20 openpyxl>=3.1.5 \ No newline at end of file