mirror of
https://github.com/Donkie/Spoolman.git
synced 2026-10-19 00:29:46 -05:00
The parallel per-platform builds shared one uv cache mount, so they queued on uv's cache lock. When uv.lock changed, the emulated armv7 sync held it long enough for the others to hit uv's 300 s lock timeout and fail publish-images.
103 lines
3.9 KiB
Docker
103 lines
3.9 KiB
Docker
FROM python:3.14-slim-bookworm AS python-builder
|
|
|
|
# A multi-platform build runs this stage once per platform in parallel. Each gets
|
|
# its own uv cache: wheels are per-platform anyway, and one shared cache made the
|
|
# platforms queue on uv's cache lock until the slow emulated armv7 sync pushed the
|
|
# others past uv's 300 s lock timeout whenever uv.lock changed.
|
|
ARG TARGETARCH
|
|
ARG TARGETVARIANT
|
|
|
|
ENV UV_COMPILE_BYTECODE=1
|
|
ENV UV_LINK_MODE=copy
|
|
ENV UV_NO_DEV=1
|
|
ENV UV_PYTHON_DOWNLOADS=0
|
|
|
|
# Install system dependencies
|
|
# No python3-dev: the base image already ships the 3.14 headers, and python3-dev
|
|
# would pull in Debian's whole python3.11 stack. patchelf is for armv7, see below.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
g++ \
|
|
libpq-dev \
|
|
libffi-dev \
|
|
patchelf \
|
|
&& apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install UV
|
|
RUN pip install --no-cache-dir uv
|
|
|
|
# Install dependencies
|
|
WORKDIR /home/app/spoolman
|
|
RUN --mount=type=cache,id=uv-${TARGETARCH}${TARGETVARIANT},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 \
|
|
&& uv cache prune --ci
|
|
|
|
# greenlet ships no 32-bit ARM wheel, so on armv7 it is compiled from source.
|
|
# setuptools links the C++ extension with gcc, which leaves libstdc++ out of the
|
|
# .so's NEEDED list, and it then crashes at import with an undefined libstdc++
|
|
# typeinfo symbol, taking startup down during the DB migration. Add libstdc++ to
|
|
# the NEEDED list so the loader pulls it in. Only armv7 is affected; amd64 and
|
|
# arm64 use a correctly linked prebuilt wheel. Done before the app is copied in so
|
|
# the layer stays cached across source-only changes.
|
|
RUN if [ "$(uname -m)" = "armv7l" ]; then \
|
|
patchelf --add-needed libstdc++.so.6 \
|
|
"$(find /home/app/spoolman/.venv -name '_greenlet*.so')"; \
|
|
fi
|
|
|
|
# Copy and install app. No --chown here: the "app" user only exists in the
|
|
# runner stage, and Podman (unlike Docker/BuildKit) refuses to resolve it. Final
|
|
# ownership is set when these files are copied into the runner stage below.
|
|
COPY migrations /home/app/spoolman/migrations
|
|
COPY spoolman /home/app/spoolman/spoolman
|
|
COPY alembic.ini README.md uv.lock pyproject.toml /home/app/spoolman/
|
|
RUN --mount=type=cache,id=uv-${TARGETARCH}${TARGETVARIANT},target=/root/.cache/uv \
|
|
uv sync --locked \
|
|
&& uv cache prune --ci
|
|
|
|
FROM python:3.14-slim-bookworm AS python-runner
|
|
|
|
LABEL org.opencontainers.image.source=https://github.com/Donkie/Spoolman
|
|
LABEL org.opencontainers.image.description="Keep track of your inventory of 3D-printer filament spools."
|
|
LABEL org.opencontainers.image.licenses=MIT
|
|
|
|
# Install gosu for privilege dropping
|
|
RUN apt-get update && apt-get install -y \
|
|
gosu \
|
|
&& apt-get clean \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Add local user so we don't run as root
|
|
RUN useradd -u 1000 -U app \
|
|
&& mkdir -p /home/app/.local/share/spoolman \
|
|
&& chown -R app:app /home/app/.local/share/spoolman
|
|
|
|
# Copy built clients. The new Svelte client (client_v2) is served by default; the
|
|
# legacy React client (client/dist) is kept for the SPOOLMAN_LEGACY_CLIENT fallback.
|
|
COPY --chown=app:app ./client/dist /home/app/spoolman/client/dist
|
|
COPY --chown=app:app ./client_v2/build /home/app/spoolman/client_v2/build
|
|
|
|
# Copy built app
|
|
COPY --chown=app:app --from=python-builder /home/app/spoolman /home/app/spoolman
|
|
|
|
COPY entrypoint.sh /home/app/spoolman/entrypoint.sh
|
|
RUN chmod +x /home/app/spoolman/entrypoint.sh
|
|
|
|
WORKDIR /home/app/spoolman
|
|
|
|
ENV PATH="/home/app/spoolman/.venv/bin:${PATH}"
|
|
|
|
ARG GIT_COMMIT=unknown
|
|
ARG BUILD_DATE=unknown
|
|
ENV GIT_COMMIT=${GIT_COMMIT}
|
|
ENV BUILD_DATE=${BUILD_DATE}
|
|
|
|
# Write GIT_COMMIT and BUILD_DATE to a build.txt file
|
|
RUN echo "GIT_COMMIT=${GIT_COMMIT}" > build.txt \
|
|
&& echo "BUILD_DATE=${BUILD_DATE}" >> build.txt
|
|
|
|
# Run command
|
|
EXPOSE 8000
|
|
ENTRYPOINT ["/home/app/spoolman/entrypoint.sh"]
|