feat(ops): W4-B single-container packaging, DATA_DIR, backup/restore
- DATA_DIR (/data: agent-sessions, backups, exports, tmp); entrypoint chowns it to PUID/PGID then drops privileges via gosu; /app binary stays root read-only - compile with --allow-read --allow-write so mounted library roots are writable - preflight: DATA_DIR/session dir must be writable (fatal); enabled library roots and downloader path mappings checked read/write (warn + audit) - --role export-mappings (mapping manifest JSON, --compare row counts) and --role read-only-on (automation.readOnlyReconcile=true + audit) - scripts/backup.sh (pg_dump custom + mappings + agent sessions, SHA256SUMS, BACKUP_KEEP rotation) and scripts/restore.sh (checksum, refuses with live connections, psql single-transaction replay compatible with PG16, read-only reconcile on, row-count verification) - compose: app + postgres only, data volume, env example with key generation - docs: runbook deploy.md, backup-restore.md with verification record Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
8c6a922cfb
commit
34e8751b45
18 files changed
+918
-43
No files matched your search
+25
-8
@@ -10,22 +10,39 @@ ARG APP_VERSION=""
|
||||
ENV APP_VERSION=${APP_VERSION}
|
||||
RUN deno task check:tokens && cd apps/web && deno task build
|
||||
# --node-modules-dir=none + --exclude-unused-npm:只嵌入 server 依赖图可达的 npm 包(约 110 MB,而不是整个 node_modules)
|
||||
# 权限在编译时固定:--allow-read 只放 /app;不给 --allow-run / --allow-write
|
||||
# 权限在编译时固定:读写不限路径(库根/下载目录由用户挂载,位置不固定;写保护靠 /app root 只读 + 非 root 运行),不给 --allow-run
|
||||
RUN cd apps/server && deno task compile
|
||||
|
||||
FROM debian:trixie-slim
|
||||
# 不装额外包:Deno 自带 Mozilla 根证书(外呼 HTTPS 不依赖 ca-certificates),健康探测用二进制自身的 fetch
|
||||
RUN useradd --system --uid 10001 --home-dir /app --shell /usr/sbin/nologin umt
|
||||
# gosu:root 修完 DATA_DIR 属主后降权;postgresql-client:备份/恢复脚本用 pg_dump/pg_restore/psql
|
||||
# (trixie 自带 17 版客户端,可备份/恢复 16 版服务端)。Deno 自带根证书,不装 ca-certificates;健康探测用二进制自身的 fetch
|
||||
# 国内网络可 --build-arg APT_MIRROR=mirrors.ustc.edu.cn 换源
|
||||
ARG APT_MIRROR=""
|
||||
RUN if [ -n "$APT_MIRROR" ]; then sed -i "s|deb.debian.org|$APT_MIRROR|g" /etc/apt/sources.list.d/debian.sources; fi \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends gosu postgresql-client \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& groupadd --system --gid 10001 umt \
|
||||
&& useradd --system --uid 10001 --gid 10001 --home-dir /data --no-create-home --shell /usr/sbin/nologin umt \
|
||||
&& mkdir -p /data && chown 10001:10001 /data
|
||||
WORKDIR /app
|
||||
COPY --from=build --chown=root:root /src/dist/umt-server /app/umt-server
|
||||
# /app 全部 root 属主、只读:运行用户(缺省 10001,可用 PUID/PGID 覆盖)改不了二进制与静态产物
|
||||
COPY --from=build --chown=root:root --chmod=0555 /src/dist/umt-server /app/umt-server
|
||||
COPY --from=build --chown=root:root /src/apps/web/build/client /app/public
|
||||
COPY --chown=root:root --chmod=0755 docker/entrypoint.sh /app/entrypoint.sh
|
||||
COPY --chown=root:root --chmod=0555 docker/entrypoint.sh /app/entrypoint.sh
|
||||
COPY --chown=root:root --chmod=0555 scripts/backup.sh scripts/restore.sh /app/scripts/
|
||||
RUN ln -s /app/entrypoint.sh /usr/local/bin/umt
|
||||
ENV NODE_ENV=production \
|
||||
HOST=0.0.0.0 \
|
||||
PORT=4380 \
|
||||
WEB_ROOT=/app/public
|
||||
USER umt
|
||||
WEB_ROOT=/app/public \
|
||||
DATA_DIR=/data \
|
||||
PUID=10001 \
|
||||
PGID=10001
|
||||
# 以 root 启动只为修 /data 属主,entrypoint 随即 gosu 降权;api/worker/备份脚本都不以 root 运行
|
||||
VOLUME ["/data"]
|
||||
EXPOSE 4380
|
||||
# 用二进制自带的 fetch 打本机回环端口,不装 curl
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=3 CMD ["/app/umt-server", "--role", "probe"]
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=3 CMD ["/app/umt-server", "--role", "probe"]
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
CMD ["serve"]
|
||||
Reference in new issue
Block a user