From cd796bbe92e18978f2c6eede2636f2be5b7941dc Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Wed, 18 Feb 2026 11:58:17 +1100 Subject: [PATCH] fix: Update Dockerfile --- Dockerfile | 66 +++++++++++++++++++++++++++++++++++++++++++++--------- main.py | 20 +++++++---------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8bccc44..29d4173 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,63 @@ -FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder +# syntax=docker/dockerfile:1 + +### Build stage ### +FROM python:3.13-alpine AS build + +# Install build dependencies for Pillow and other native wheels +RUN apk add --no-cache \ + build-base \ + jpeg-dev zlib-dev freetype-dev + +# Copy uv (fast Python package manager) +COPY --from=ghcr.io/astral-sh/uv:0.8.21 /uv /uvx /bin/ WORKDIR /app +COPY pyproject.toml uv.lock ./ -COPY requirements.txt /app -RUN --mount=type=cache,target=/root/.cache/pip \ - python3 -m pip install -r requirements.txt +# Install dependencies into a virtual environment +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked -COPY . /app +# Copy only app source files +COPY blueprints blueprints +COPY main.py server.py curl.py tools.py mail.py cache_helper.py ./ +COPY templates templates +COPY data data +COPY pwa pwa +COPY .well-known .well-known -# Optionally mount /data to store the data -# VOLUME /data +# Clean up caches and pycache +RUN rm -rf /root/.cache/uv +RUN find . -type d -name "__pycache__" -exec rm -rf {} + -ENTRYPOINT ["python3"] -CMD ["main.py"] -FROM builder as dev-envs \ No newline at end of file +### Runtime stage ### +FROM python:3.13-alpine AS runtime +ENV PATH="/app/.venv/bin:$PATH" + +# Create non-root user +RUN addgroup -g 1001 appgroup && \ + adduser -D -u 1001 -G appgroup -h /app appuser + +WORKDIR /app +RUN apk add --no-cache curl + + +# Copy only whats needed for runtime +COPY --from=build --chown=appuser:appgroup /app/.venv /app/.venv +COPY --from=build --chown=appuser:appgroup /app/blueprints /app/blueprints +COPY --from=build --chown=appuser:appgroup /app/templates /app/templates +COPY --from=build --chown=appuser:appgroup /app/data /app/data +COPY --from=build --chown=appuser:appgroup /app/pwa /app/pwa +COPY --from=build --chown=appuser:appgroup /app/.well-known /app/.well-known +COPY --from=build --chown=appuser:appgroup /app/main.py /app/ +COPY --from=build --chown=appuser:appgroup /app/server.py /app/ +COPY --from=build --chown=appuser:appgroup /app/curl.py /app/ +COPY --from=build --chown=appuser:appgroup /app/tools.py /app/ +COPY --from=build --chown=appuser:appgroup /app/mail.py /app/ +COPY --from=build --chown=appuser:appgroup /app/cache_helper.py /app/ + +USER appuser +EXPOSE 5000 + +ENTRYPOINT ["python3", "main.py"] diff --git a/main.py b/main.py index 376fcd5..8ae7d5b 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,3 @@ -from flask import Flask -from server import app import server from gunicorn.app.base import BaseApplication import os @@ -20,23 +18,21 @@ class GunicornApp(BaseApplication): def load(self): return self.application - - -if __name__ == '__main__': +if __name__ == "__main__": dotenv.load_dotenv() - - workers = os.getenv('WORKERS', 1) - threads = os.getenv('THREADS', 2) + + workers = os.getenv("WORKERS", 1) + threads = os.getenv("THREADS", 2) workers = int(workers) threads = int(threads) options = { - 'bind': '0.0.0.0:5000', - 'workers': workers, - 'threads': threads, + "bind": "0.0.0.0:5000", + "workers": workers, + "threads": threads, } gunicorn_app = GunicornApp(server.app, options) - print(f'Starting server with {workers} workers and {threads} threads', flush=True) + print(f"Starting server with {workers} workers and {threads} threads", flush=True) gunicorn_app.run()