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:
rootandClaude Opus 5.5 committed 2026-09-27 21:27:55 +08:00
1 parent 8c6a922cfb
commit 34e8751b45
18 files changed
+918 -43

No files matched your search

+19 -5
View File
@@ -1,7 +1,8 @@
# 生产/试运行部署:app(单容器:API + worker + web 静态)+ postgres 两个服务。
# 用法:
# export SECRET_MASTER_KEY=$(openssl rand -hex 32) POSTGRES_PASSWORD=$(openssl rand -hex 16)
# 生产/试运行部署:只有两个服务 —— app(单容器:API + worker + web 静态,单端口 4380)+ postgres。
# 用法(详见 docs/runbook/deploy.md):
# cp docker/compose.env.example .env # 按注释生成 SECRET_MASTER_KEY / POSTGRES_PASSWORD
# docker compose up -d --build
# docker compose logs app | grep -i setup # 首次启动打印一次性 setup token
# 开发只起数据库用 docker-compose.dev.yml。
name: umt
@@ -26,6 +27,7 @@ services:
interval: 5s
timeout: 3s
retries: 20
stop_grace_period: 30s
logging: *logging
app:
@@ -33,6 +35,7 @@ services:
context: .
args:
APP_VERSION: ${APP_VERSION:-}
APT_MIRROR: ${APT_MIRROR:-}
image: uhd-media-tool:${APP_VERSION:-latest}
restart: unless-stopped
depends_on:
@@ -41,12 +44,23 @@ services:
environment:
NODE_ENV: production
DATABASE_URL: postgres://umt:${POSTGRES_PASSWORD}@postgres:5432/umt
SECRET_MASTER_KEY: ${SECRET_MASTER_KEY:?请设置 SECRET_MASTER_KEY(至少 32 字节随机串)}
SECRET_MASTER_KEY: ${SECRET_MASTER_KEY:?请设置 SECRET_MASTER_KEY(openssl rand -hex 32)}
LOG_LEVEL: ${LOG_LEVEL:-info}
# 运行用户:DATA_DIR 由 entrypoint chown 成它;媒体库/下载目录需对它可读写
PUID: ${PUID:-10001}
PGID: ${PGID:-10001}
BACKUP_KEEP: ${BACKUP_KEEP:-14}
ports:
- "${UMT_PORT:-4380}:4380"
- "${UMT_BIND:-0.0.0.0}:${UMT_PORT:-4380}:4380"
volumes:
# 应用数据:agent-sessions/ backups/ exports/ tmp/
- umt-data:/data
# 媒体库根与下载缓存目录按需挂载(容器内路径 = 控制台里登记的库根 / 路径映射 local 前缀):
# - /srv/media:/media
# - /srv/downloads:/downloads
stop_grace_period: 15s
logging: *logging
volumes:
umt-pg-data:
umt-data: