mirror of
https://github.com/hectorqin/reader.git
synced 2026-11-10 21:11:08 +08:00
按产品设计 v0.2 落地服务端,覆盖第一版范围中的扫描、元数据、权限与同步。 核心决策: - 书籍主键用 dc:identifier + 内容哈希,不用文件路径。 重命名/移动不丢进度,副本自动合并,重新编码的文件保持独立。 - 库目录只读挂载,写操作全部落到 DATA_DIR。 启动时断言 DATA_DIR 不在 BOOKS_DIR 内,路径解析统一走 resolveInside 拦截逃逸,扫描不跟随符号链接。 - 元数据优先级:手动修改 > 内嵌 > provider > 文件名解析。 手动修改独立成表,扫描永远碰不到,可单字段撤销。 - 中文文件名解析采取保守策略,无证据时不猜测作者方向。 - 离线合并用 LWW,笔记删除写墓碑,批次单事务。 - 无原生编译依赖:node:sqlite 与 scrypt 均为内置模块。 交付: - Fastify + TypeScript 服务端,Docker 单容器 - 27 个自动化测试用例全部通过 - AGPL-3.0,README 做到一条命令跑起来 - CNB 流水线:typecheck / test / build
44 lines
1.5 KiB
Docker
44 lines
1.5 KiB
Docker
# --- build stage -------------------------------------------------------------
|
|
FROM docker.cnb.cool/dockerhub/node:24-alpine AS build
|
|
WORKDIR /app
|
|
|
|
COPY package.json package-lock.json* ./
|
|
# Install dev deps too: the TypeScript toolchain is needed to compile.
|
|
RUN npm ci --include=dev
|
|
|
|
COPY tsconfig.json ./
|
|
COPY src ./src
|
|
RUN npm run build
|
|
|
|
# Strip dev dependencies for the runtime image.
|
|
RUN npm prune --omit=dev
|
|
|
|
# --- runtime stage -----------------------------------------------------------
|
|
FROM docker.cnb.cool/dockerhub/node:24-alpine AS runtime
|
|
WORKDIR /app
|
|
|
|
ENV NODE_ENV=production \
|
|
BOOKS_DIR=/books \
|
|
DATA_DIR=/data \
|
|
PORT=8080
|
|
|
|
# Run as an unprivileged user. The library mount is read-only, so this user
|
|
# only ever needs write access to /data.
|
|
RUN addgroup -S reader && adduser -S reader -G reader \
|
|
&& mkdir -p /data /books && chown -R reader:reader /data /books
|
|
|
|
COPY --from=build --chown=reader:reader /app/node_modules ./node_modules
|
|
COPY --from=build --chown=reader:reader /app/dist ./dist
|
|
COPY --chown=reader:reader package.json ./
|
|
|
|
USER reader
|
|
EXPOSE 8080
|
|
VOLUME ["/data"]
|
|
|
|
# The healthcheck hits the unauthenticated endpoint so an orchestrator can tell
|
|
# "server up but library unreadable" from "server down".
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8080)+'/api/v1/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
|
|
CMD ["node", "dist/main.js"]
|