mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
f79874317d
The KOReader plugin sends md5(password) as x-auth-key, which can never match the bcrypt hash of the plaintext password. The auth guard ran a cost-12 bcrypt compare first, so every authenticated request spent about 250 ms of CPU and stalled other traffic before the md5 fallback accepted it. Check md5 first and keep bcrypt as the fallback for clients that send the plaintext password, so the accepted credentials are unchanged. A plugin auth call drops from about 285 ms to 8 ms. Bump the KOReader plugin to 2.2.0. The plugin changed after the 2.1.0 release shipped in v3.6.0 (series sorting, series selection, file browser exit, paged Shelves list) without a version bump. Also fix three metadata-fetch tests that were failing on main sincecfcd4ca52kept single-digit tokens in tokenizeTitleText. A volume digit in the query diluted the word overlap in scoreTitleMatch, so an ebook candidate fell under the relevance floor and a manga outranked it. scoreTitleMatch now drops lone digits again; symmetricTitleSimilarity keeps them to tell volumes apart. Also align the pnpm version installed in both Dockerfiles with the packageManager field. Sincef2a7a1118the images installed pnpm 11.22.0 while package.json pinned 11.28.9, so pnpm tried to switch itself and failed the arm64 image build with a missing @pnpm/exe lockfile entry. Closes #1983 Ref #2037
96 lines
4.1 KiB
Docker
96 lines
4.1 KiB
Docker
ARG NODE_IMAGE=node:26.12.1-alpine3.23@sha256:bc2b334006f15c7167bbeb2f08f28c2df883f7594a0470e04454ebe7560cfe68
|
|
|
|
FROM ${NODE_IMAGE} AS base
|
|
RUN npm install -g pnpm@11.28.9
|
|
|
|
# Stage 1: Build client
|
|
FROM base AS client-builder
|
|
WORKDIR /app
|
|
|
|
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
|
|
COPY patches/ ./patches/
|
|
COPY packages/types/package.json ./packages/types/
|
|
COPY client/package.json ./client/
|
|
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
|
|
pnpm install --filter client... --frozen-lockfile
|
|
|
|
COPY packages/ ./packages/
|
|
COPY client/ ./client/
|
|
# pnpm 11 defaults verifyDepsBeforeRun to "install", so running a script
|
|
# re-installs first. Each stage installed its own filtered subset with a frozen
|
|
# lockfile two steps up, and no stage carries the whole workspace, so that
|
|
# re-install is both redundant and wrong: it resolves against a partial
|
|
# workspace. In the server stage it is fatal, because client/ is absent and the
|
|
# @embedpdf patches then look unused.
|
|
RUN pnpm --config.verify-deps-before-run=false --filter client run build-only
|
|
|
|
# Stage 2: Build server + create deploy bundle
|
|
FROM base AS server-builder
|
|
WORKDIR /app
|
|
|
|
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
|
|
COPY patches/ ./patches/
|
|
COPY packages/types/package.json ./packages/types/
|
|
COPY server/package.json ./server/
|
|
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
|
|
pnpm install --filter server... --frozen-lockfile
|
|
|
|
COPY packages/ ./packages/
|
|
COPY server/ ./server/
|
|
RUN pnpm --config.verify-deps-before-run=false --filter server run build
|
|
|
|
# pnpm deploy prunes to prod deps; dist/ is gitignored so copy it in after.
|
|
RUN pnpm --config.allow-unused-patches=true --filter server deploy --prod --legacy /deploy
|
|
RUN cp -r /app/server/dist /deploy/dist
|
|
RUN mkdir -p /deploy/migrations && cp -r /app/server/src/db/migrations/. /deploy/migrations/
|
|
|
|
# Stage 3: Runtime image
|
|
FROM ${NODE_IMAGE} AS runtime
|
|
WORKDIR /app
|
|
|
|
ARG APP_VERSION=dev
|
|
ENV APP_VERSION=${APP_VERSION}
|
|
ENV KOBO_CLOUDSCRAPER_PYTHON=/opt/bookorbit-python/bin/python
|
|
ENV KOREADER_PLUGIN_PATH=/app/koreader-plugin/bookorbit.koplugin
|
|
|
|
COPY server/requirements/kobo-cloudscraper.txt /tmp/kobo-cloudscraper-requirements.txt
|
|
|
|
# pip is build-only here. Leaving it installed also leaves pip/_vendor/vendor.txt,
|
|
# which Trivy reads as installed msgpack and setuptools and fails the image scan on.
|
|
RUN apk upgrade --no-cache && \
|
|
apk add --no-cache 'libexpat>=2.9.0-r0' poppler-utils djvulibre util-linux su-exec ffmpeg python3 py3-pip tini tzdata && \
|
|
python3 -m venv /opt/bookorbit-python && \
|
|
/opt/bookorbit-python/bin/python -m pip install --no-cache-dir -r /tmp/kobo-cloudscraper-requirements.txt && \
|
|
/opt/bookorbit-python/bin/python -m pip uninstall -y pip && \
|
|
apk del py3-pip && \
|
|
rm -f /tmp/kobo-cloudscraper-requirements.txt && \
|
|
rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx
|
|
|
|
ENV NODE_ENV=production
|
|
ENV PORT=3000
|
|
|
|
COPY --from=server-builder --chown=node:node /deploy ./
|
|
COPY --from=client-builder --chown=node:node /app/client/dist ./public
|
|
# The server reads its own translated text (achievements, monthly challenges) from the web's catalogs.
|
|
COPY --from=client-builder --chown=node:node /app/client/src/locales ./locales
|
|
COPY --from=server-builder --chown=node:node /app/server/entrypoint.sh /app/server/file-env.sh ./
|
|
COPY --chown=node:node LICENSE NOTICE ADDITIONAL_TERMS.md ./
|
|
COPY --chown=node:node server/bin/kepubify/ ./bin/kepubify/
|
|
COPY --chown=node:node koreader-plugin/bookorbit.koplugin/ ./koreader-plugin/bookorbit.koplugin/
|
|
|
|
RUN sed -i 's/\r$//' /app/entrypoint.sh /app/file-env.sh && chmod +x /app/entrypoint.sh /app/bin/kepubify/* && mkdir -p /books /data/covers /data/book-bucket /tmp && chown -R node:node /data /tmp
|
|
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
CMD host="$(printf '%s' "${HOST:-}" | tr -d '[:space:]')"; \
|
|
case "$host" in \
|
|
''|0.0.0.0) host=127.0.0.1 ;; \
|
|
::) host='[::1]' ;; \
|
|
*:*) host="[$host]" ;; \
|
|
esac; \
|
|
wget -q -T 4 -O /dev/null "http://${host}:${PORT:-3000}/api/v1/health"
|
|
|
|
ENTRYPOINT ["/sbin/tini", "-s", "--"]
|
|
CMD ["sh", "/app/entrypoint.sh"]
|