# Multi-stage build example for HXBooks FROM ghcr.io/astral-sh/uv:python3.14-alpine AS builder ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy # Omit development dependencies ENV UV_NO_DEV=1 # Disable Python downloads, because we want to use the system interpreter # across both images. If using a managed Python version, it needs to be # copied from the build image into the final image; see `standalone.Dockerfile` # for an example. ENV UV_PYTHON_DOWNLOADS=0 WORKDIR /app RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --locked --no-install-project COPY . /app RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --locked # Then, use a final image without uv FROM python:3.14-alpine # It is important to use the image that matches the builder, as the path to the # Python executable must be the same, e.g., using `python:3.11-slim-bookworm` # will fail. # Copy the application from the builder COPY --from=builder /app /app # Copy and setup entrypoint script COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh # Create shared directories for volumes RUN mkdir -p /shared/static # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # Set Flask app for migrations ENV FLASK_APP="src.hxbooks.app:create_app()" # Use `/app` as the working directory WORKDIR /app # Set entrypoint and default command ENTRYPOINT ["docker-entrypoint.sh"] CMD ["hxbooks", "serve", "--host", "0.0.0.0", "--port", "5000"]