# syntax=docker/dockerfile:1 FROM ghcr.io/astral-sh/uv:python3.14-trixie-slim # Prevents Python from buffering stdout and stderr ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1 ENV PATH=/app/.venv/bin:$PATH WORKDIR /app # uv installs the locked dependencies without the dev tools. The app comes after them, so a code change reuses this # layer. COPY pyproject.toml uv.lock ./ RUN UV_COMPILE_BYTECODE=1 UV_PYTHON_DOWNLOADS=never \ uv sync --locked --no-default-groups --no-install-project --no-cache # --chmod sets the mode as part of the copy, so every user can read the app. The container can # run as any user, also with rootless Docker or Podman, and root owns the copies otherwise. COPY --chmod=a+rX data ./data COPY --chmod=a+rX bindery ./bindery EXPOSE 8085 # The commands come from /app/.venv/bin. "uv run" would try to sync the root-owned environment as the container user. HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=3 \ CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8085/api/health', timeout=5)"] # One worker only, because the job and scheduler threads run inside it. Bindery does not use the control socket, and # its default folder, $HOME/.gunicorn, is not writable for a container user without a home folder. CMD ["gunicorn", "--bind", "0.0.0.0:8085", "--workers", "1", "--threads", "4", "--timeout", "300", \ "--no-control-socket", "bindery.web:app"]