docassemble 1.10.15 日常运维与升级指南
docassemble 1.10.15 单容器全栈形态的日常运维实录:supervisor 进程巡检、日志与数据库/Redis 检查、cron 自动备份机制拆解、手动 pg_dump/pg_restore 备份恢复闭环验证、Monitor/Logs 监控页、CONTAINERROLE 分角色扩缩容、update.sh/reset 升级链路与镜像级回滚,全部实测回显。
docassemble 1.10.15 日常运维与升级指南
目标:覆盖 docassemble 1.10.15 单容器全栈部署上线后的运维闭环——日常巡检、备份与恢复、监控告警、扩缩容、升级与回滚、故障排查入口。本文全部命令与回显均在 《docassemble 1.10.15 Docker Compose 部署指南》 的部署环境上实测通过:Ubuntu 26.04.1 LTS 宿主,compose 项目
docassemble-1.10.15-stack,容器docassemble-1.10.15-web,端口 8139→80。
一、环境信息
- 应用:docassemble 1.10.15(官方全栈镜像
jhpyle/docassemble,镜像 IDaaa4a57e7d06,虚拟大小 15.8GB) - 进程管理:supervisord(PID 1),内置组件按 supervisor 程序单元启停
- 内置组件版本(实测):Python 3.14.4 / Flask 3.1.3 / PostgreSQL 18.6 / Redis 8.0.5 / RabbitMQ 4.0.5 / nginx 1.28.3 / Celery 5.6.3
- Python 虚拟环境:
/usr/share/docassemble/local3.14(环境变量DAPYTHON可覆盖) - 主配置:
/usr/share/docassemble/config/config.yml(实测属主www-data:www-data,3976B) - 数据目录:
/usr/share/docassemble/files/(访谈文件/上传件/生成文档) - 日志目录:
/usr/share/docassemble/log/;Web 访问日志/var/log/nginx/ - 备份落点:
/usr/share/docassemble/backup/(唯一必挂卷da-backup) - 数据库连接:
PGPASSWORD=abc123 psql -U docassemble -d docassemble -h localhost(abc123为出厂默认口令,生产必改) - Web 管理入口:
/config(配置编辑)、/monitor(监控)、/logs(日志查看)、/playgroundpackages?project=default(包管理),均需管理员登录
版本确认实测:
docker exec docassemble-1.10.15-web bash -lc 'source /usr/share/docassemble/local3.14/bin/activate && pip show docassemble.base | head -3'
Name: docassemble.base
Version: 1.10.15
Summary: The base components of the docassemble system.
二、日常巡检
日常巡检的目标是五分钟内确认「进程齐、日志净、库可读、缓存活、盘不涨」。以下命令逐条实测。
2.1 服务与进程状态
docker compose -f /opt/data/quzuo/tmp/docassemble/stack/docker-compose.yml ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docassemble-1.10.15-web jhpyle/docassemble:latest "/usr/bin/supervisor…" docassemble 2 hours ago Up 2 hours 25/tcp, 443/tcp, 465/tcp, 514/tcp, 4369/tcp, 5432/tcp, 5671-5672/tcp, 6379/tcp, 8080-8082/tcp, 9001/tcp, 25672/tcp, 0.0.0.0:8139->80/tcp, [::]:8139->80/tcp
容器内进程全景用 supervisorctl status(实测全文,uptime 为取证时刻值):
docker exec docassemble-1.10.15-web supervisorctl status
apache2 STOPPED Not started
celery RUNNING pid 3442, uptime 1:49:43
celerysingle RUNNING pid 3443, uptime 1:49:43
cron RUNNING pid 1662, uptime 1:53:16
exim4 RUNNING pid 2027, uptime 1:53:13
main:initialize RUNNING pid 7, uptime 2:10:37
main:postgres RUNNING pid 177, uptime 2:09:56
main:redis RUNNING pid 234, uptime 2:09:50
nascent STOPPED Nov 01 07:40 AM
nginx RUNNING pid 1569, uptime 1:53:20
nltk RUNNING pid 1374, uptime 1:53:41
rabbitmq RUNNING pid 3125, uptime 1:49:45
reset EXITED Nov 01 07:44 AM
sync EXITED Nov 01 09:26 AM
syslogng STOPPED Not started
unoserver RUNNING pid 1600, uptime 1:53:18
update STOPPED Not started
uwsgi RUNNING pid 1510, uptime 1:53:25
watchdog RUNNING pid 9, uptime 2:10:37
websockets RUNNING pid 2771, uptime 1:49:49
判读要点(实测归纳):
- 必须 RUNNING 的核心单元:
main:postgres、main:redis、rabbitmq、celery、celerysingle、uwsgi、nginx、websockets、watchdog、cron。 apache2 STOPPED是正常状态:本部署DAWEBSERVER取默认 nginx(实测config.yml中web server: nginx),apache 单元休眠。reset EXITED (exit status 0)、sync EXITED是正常状态:一次性任务跑完即退出,容器日志实测2026-11-01 07:44:11,063 INFO exited: reset (exit status 0; expected)。nascent STOPPED、syslogng STOPPED、update STOPPED默认休眠:nascent 是可选的 NLP 组件,syslogng 仅多机日志汇聚时启用,update由 Web 包管理页按需触发(见「六、升级与回滚」)。
2.2 应用与系统日志
日志目录实测清单:
docker exec docassemble-1.10.15-web ls /usr/share/docassemble/log/
access.log
docassemble.log
error.log
single_worker.log
uwsgi.log
websockets.log
worker.log
各文件分工:docassemble.log 是应用主日志(访谈执行报错、用户操作审计都在这,排障第一现场);uwsgi.log 是 WSGI 服务日志;worker.log/single_worker.log 是 Celery 任务日志;websockets.log 是实时通信日志;access.log/error.log 是 nginx 站点日志。另有 supervisor 层日志在 /var/log/supervisor/<程序名>-stdout---supervisor-*.log 与对应 -stderr- 文件。
巡检抽尾(实测节选,docassemble.log 尾部恰好留有排障样本):
docker exec docassemble-1.10.15-web tail -2 /usr/share/docassemble/log/docassemble.log
docassemble: ip=10.89.61.1 i=docassemble.playground1:g25final.yml uid=idJ6ZcaFkHNnHosBLP38lCWw2MXjAQ4D user=admin@example.com 2026-11-01 22:20:47 Tried to run _internal["answers"]['ID greeting'] = int('exit') and got error ValueError: invalid literal for int() with base 10: 'exit'
docassemble: ip=10.89.61.1 i=docassemble.playground1:g25final.yml uid=idJ6ZcaFkHNnHosBLP38lCWw2MXjAQ4D user=admin@example.com 2026-11-01 22:21:12 Redirecting because of an exit.
每行格式为 docassemble: ip=<来源> i=<访谈路径> uid=<会话> user=<账号> <时间> <事件>,可直接按访谈/用户 grep 定位问题会话。
2.3 数据库与缓存
docker exec docassemble-1.10.15-web bash -lc \
"echo \"SELECT count(*) FROM information_schema.tables WHERE table_schema='public';\" \
| PGPASSWORD=abc123 psql -U docassemble -d docassemble -h localhost -At"
# 25
SELECT version(); 实测:
PostgreSQL 18.6 (Ubuntu 18.6-0ubuntu0.26.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0, 64-bit
Redis 双库检查(官方口径:-n 1 系统级缓存,-n 2 是 DARedis 用户数据):
docker exec docassemble-1.10.15-web redis-cli -n 1 dbsize # 16
docker exec docassemble-1.10.15-web redis-cli -n 2 dbsize # 0
-n 2 为 0 属正常:只有访谈里显式使用 DARedis 对象才会有数据。
2.4 资源与磁盘
docker exec docassemble-1.10.15-web bash -lc 'df -h / | tail -1; free -m | head -2'
overlay 443G 263G 162G 62% /
total used free shared buff/cache available
Mem: 15941 8616 852 291 7090 7325
⚠️ 注意:官方 Docker 文档口径镜像「下载约 4GB、运行后约 10GB」,本环境实测镜像虚拟大小 15.8GB、容器可写层 1.76GB——磁盘水位巡检阈值建议按 40GB 起评(官方最低要求),访谈附件与生成文档多的实例要单独盯
files/目录增速。
2.5 版本与配置一致性
管理员登录后访问 /config 页(实测 allow configuration editing: true,页面 200),页脚直接回显运行版本:
Version 1.10.15
这是官方推荐的版本自查入口(「To see what version of docassemble you are running, log in as an administrator and go to Configuration」,官方安装文档原文)。配置改动后必须走 supervisorctl restart uwsgi 或 supervisorctl start reset 生效,见「六、升级与回滚」。
三、备份与恢复
docassemble 全栈镜像的备份是「双轨制」:安全关机时一次性全量收卷 + 每日 cron 增量滚动。本节先拆解自动机制(读实测脚本),再实测手动备份与恢复闭环。
3.1 自动备份机制拆解(实测脚本)
每日任务由 /etc/cron.daily/docassemble 承担(cron 单元 RUNNING 即会执行)。实测脚本关键段:
# 证书备份(USEHTTPS+USELETSENCRYPT 时):certbot renew 后打包
tar -zcf /tmp/letsencrypt.tar.gz etc/letsencrypt
cp /tmp/letsencrypt.tar.gz "${DA_ROOT}/backup/letsencrypt.tar.gz"
# 访谈内定时任务
"${DA_ROOT}/webapp/run-cron.sh" cron_daily
# 日志/配置/文件 rsync 进 backup(--delete 保持镜像一致)
rsync -auq --delete "${LOGDIRECTORY}" "${DA_ROOT}/backup/"
rm -f "${DA_ROOT}/backup/config.yml"
cp "${DA_CONFIG_FILE}" "${DA_ROOT}/backup/config.yml"
rsync -auq --delete "${DA_ROOT}/files" "${DA_ROOT}/backup/"
# PostgreSQL:每库 pg_dump 自定义格式,先落临时目录再 rsync 进 backup
PGBACKUPDIR=`mktemp -d`
chown postgres:postgres "${PGBACKUPDIR}"
su postgres -c 'psql -Atc "SELECT datname FROM pg_database" postgres' | grep -v -e template -e postgres | awk -v backupdir="$PGBACKUPDIR" '{print "cd /tmp; su postgres -c \"pg_dump -F c -f " backupdir "/" $1 " " $1 "\""}' | bash
rsync -auq "$PGBACKUPDIR/" "${DA_ROOT}/backup/postgres"
# Redis:RDB 快照复制
cp /var/lib/redis/dump.rdb "${DA_ROOT}/backup/redis.rdb"
# 滚动备份目录 MM-DD(当天全量),并按 DABACKUPDAYS 清理过期目录
MONTHDAY=$(date +%m-%d)
BACKUPDIR="${DA_ROOT}/backup/$MONTHDAY"
rsync -auq "${DA_ROOT}/files" "${BACKUPDIR}/"
rsync -auq "${DA_ROOT}/config" "${BACKUPDIR}/"
rsync -auq "${LOGDIRECTORY}" "${BACKUPDIR}/"
rm -rf `find "${DA_ROOT}/backup" -maxdepth 1 -path '*[0-9][0-9]-[0-9][0-9]' -a -type 'd' -a -mtime +${DABACKUPDAYS:-14} -print`
解读:备份内容 = 配置 + 访谈/上传文件 + 日志 + 数据库逻辑备份 + Redis RDB + 证书;滚动目录保留 backup days: 14(实测 config.yml 值,DABACKUPDAYS 环境变量可调);配了 S3/Azure 时同内容改传云存储(脚本内 s4cmd dsync / az storage blob upload 分支)。
安全关机(docker stop 留足 600s / docker compose down)时另有全量收卷,backup 卷当前实测内容:
docker exec docassemble-1.10.15-web ls -la /usr/share/docassemble/backup/files/
total 28
drwxr-xr-x 7 www-data www-data 4096 Nov 1 22:07 .
drwxr-xr-x 3 root root 4096 Nov 1 22:31 ..
drwxr-xr-x 3 www-data www-data 4096 Nov 1 22:07 playground
drwxrwxr-x 3 www-data www-data 4096 Nov 1 20:40 playgroundmodules
drwxr-xr-x 3 www-data www-data 4096 Nov 1 22:07 playgroundsources
drwxr-xr-x 3 www-data www-data 4096 Nov 1 22:07 playgroundstatic
drwxr-xr-x 3 www-data www-data 4096 Nov 1 22:07 playgroundtemplate
💡 技术拓展:备份策略不止本文所用的「逻辑+文件级」一种。常见形态对比——
策略 原理 适用/取舍 逻辑备份(pg_dump -F c) 导出 SQL 对象与数据,自定义压缩格式可按表恢复 跨版本可恢复、体积小;不含集群级对象外的运行时状态。本文数据库采用 文件级同步(rsync) 增量复制 config/files/log 目录 简单直接、可 --delete 保持一致。本文附件采用 物理快照(pg_basebackup/卷快照) 直接复制数据目录 恢复快、必须同大版本;本镜像未采用 滚动快照(MM-DD 目录) 每日全量副本+保留 N 天 可回溯任意一天。本文 DABACKUPDAYS=14 采用 本栈选择逻辑备份+文件级双轨,核心动因是镜像设计为「除 backup 卷外全部可丢弃」,升级/迁移跨 PG 大版本时逻辑备份是唯一安全通道。
3.2 手动数据库备份(实测)
先踩一个真实权限坑:直接以 postgres 用户往 backup 目录写会失败——backup 属主是 root:
docker exec docassemble-1.10.15-web bash -lc \
'su postgres -c "pg_dump -F c -f /usr/share/docassemble/backup/manual-test.pgd docassemble"'
pg_dump: error: could not open output file "/usr/share/docassemble/backup/manual-test.pgd": Permission denied
正确做法与官方 cron 脚本同款:先落 postgres 可写的临时目录,再由 root rsync 进 backup。实测:
docker exec docassemble-1.10.15-web bash -lc \
'D=$(mktemp -d); chown postgres:postgres $D; \
su postgres -c "cd /tmp; pg_dump -F c -f $D/docassemble docassemble"; \
ls -la $D'
total 104
drwx------ 2 postgres postgres 4096 Nov 1 22:34 .
-rw-rw-r-- 1 postgres postgres 98187 Nov 1 22:34 docassemble
备份产物校验用 pg_restore -l(只读目录不恢复,实测命令与回显;临时目录内联重建):
docker exec docassemble-1.10.15-web bash -lc \
'D=$(mktemp -d); chown postgres:postgres $D; \
su postgres -c "cd /tmp; pg_dump -F c -f $D/docassemble docassemble"; \
su postgres -c "pg_restore -l $D/docassemble" | head -12; rm -rf $D'
;
; Archive created at 2026-11-01 22:34:57 CST
; dbname: docassemble
; TOC Entries: 239
; Compression: gzip
; Dump Version: 1.16-0
; Format: CUSTOM
; Integer: 4 bytes
; Offset: 8 bytes
; Dumped from database version: 18.6 (Ubuntu 18.6-0ubuntu0.26.04.1)
; Dumped by pg_dump version: 18.6 (Ubuntu 18.6-0ubuntu0.26.04.1)
TOC 239 项、Format CUSTOM、gzip 压缩——自定义格式支持 -n/--table 选择性恢复与并行 -j 恢复,是升级前兜底备份的首选形态。
3.3 恢复演练(实测闭环)
备份不做恢复演练等于没备。实测把 3.2 的产物恢复到临时库并核对表数:
docker exec docassemble-1.10.15-web bash -lc \
'D=$(mktemp -d); chown postgres:postgres $D;
su postgres -c "cd /tmp; pg_dump -F c -f $D/docassemble docassemble";
su postgres -c "createdb test_restore";
su postgres -c "pg_restore -d test_restore $D/docassemble" && echo RESTORE_OK;
su postgres -c "psql -Atc \"SELECT count(*) FROM pg_tables WHERE schemaname='"'"'public'"'"'\" test_restore"';
su postgres -c "dropdb test_restore" && echo DROPDB_OK; rm -rf $D'
RESTORE_OK
25
DROPDB_OK
恢复到 25 张表,与 2.3 巡检的原库表数一致,备份链路验证通过。生产恢复同理:把 pg_restore -d test_restore 换成 -d docassemble(或先重建空库再恢复),随后 supervisorctl start reset 让应用重连。
3.4 整机恢复与安全关机保护
常规「重启即恢复」不需要手工干预:安全关机时全量收卷进 backup,开机 initialize.sh 反向恢复。但强杀会触发保护(实测 initialize.sh 关键段):
RESTOREFROMBACKUP=true
if [ -f /var/run/docassemble/da_running ] || [ -f /var/run/docassemble/status-rabbitmq-running ]; then
echo "initialize: unsafe shutdown detected; will not restore from backup" >&2
RESTOREFROMBACKUP=false
fi
解读:开机发现上次遗留的 da_running 标记(被 docker kill/宿主机断电级强杀),本次不会用 backup 覆盖现场——防止把最后一次安全备份之后仍在盘上的数据回滚掉。此时若需要彻底回到备份点,手动把 backup 卷内 config.yml、files/、postgres/ 对应物拷回原位后 supervisorctl start reset。这也是部署文档强制 stop_grace_period: 600s 的原因:停机命令务必给足优雅窗口(docker compose down 即可,勿加 -t 1)。
四、监控告警
4.1 内置 Monitor 页
管理员访问 http://localhost:8139/monitor(实测 200):
curl -s -b jar.txt http://localhost:8139/monitor -o /dev/null -w '%{http_code}\n'
# 200,<title>Monitor</title>
页面提供会话(Sessions)列表与「Set status to available / not available」按钮(实测页面元素),可在发版窗口把系统临时置为不可用,阻断新访谈进入。开关为 config.yml 的 enable monitor(官方文档口径默认 True,实测页面可访问即默认开启)。
4.2 Logs 页
Web 端日志查看器 http://localhost:8139/logs(实测 200,<title>Logs</title>),受 allow log viewing: true(实测 config.yml 值)控制,管理员无需进容器即可翻 docassemble.log 等文件。
⚠️ 注意:路径是
/logs,实测/log返回 404;/manage在本版本同样 404,监控页正确路径为/monitor。
4.3 进程与外部监控对接
- 进程级:
supervisorctl status可脚本化采集(非 0 退出即异常单元),supervisord 自带 XML-RPC 在 9001 端口(容器内监听,实测端口列表含 9001)。 - 存活级:
curl -s -o /dev/null -w '%{http_code}' http://localhost:8139/期望 200;启动期返回的<title>Docassemble is starting</title>可作为「未就绪」判据。 - 邮件通道:
exim4单元 RUNNING(pid 实测 2027),docassemble 的告警/通知邮件走它;enable sms interface、enable faxing在实测 config.yml 中均为 True,接了 Twilio 类服务后可启用短信/传真告警。 - 统计开关:实测
collect statistics false——默认不收集使用统计,需要业务量报表时在/config打开。
五、扩容缩容
5.1 单机内的并发调优
WSGI 并发实测来自 /usr/share/docassemble/config/docassemble.ini(uwsgi 配置,首启生成):
processes = 1
threads = 6
master = true
socket = /var/run/uwsgi/docassemble.sock
mount = /=docassemble.webapp.run:application
buffer-size = 32768
touch-reload = docassemble.wsgi
max-fd = 1048576
uwsgi.log 实测印证 worker 形态:spawned uWSGI worker 1 (pid: 3421, cores: 6)。加大 Web 并发即调 processes(改完 supervisorctl restart uwsgi)。Celery 侧由 run-celery.sh 按 nproc 与 DAMAXCELERYWORKERS/max celery processes(实测 null=自动)取小生成进程数。
5.2 按角色拆分扩容(CONTAINERROLE)
单容器全栈撑不住时,官方方案是用 CONTAINERROLE 把同一镜像拆成多节点角色部署(实测镜像内各 run-*.sh 均以 :${CONTAINERROLE:-all}: 匹配决定是否拉起对应组件)。官方扩展性文档中的角色:all、web、celery、sql、redis、rabbitmq、cron、log、mail、socket 等,组合写法如 :redis:rabbitmq:log:cron:mail。
拆分要点(官方 Docker/扩展性文档口径 + 实测 config.yml 对应项):
- Web 节点:
CONTAINERROLE=:web:,config.yml的db.host/redis/rabbitmq指向独立数据节点(实测单机形态均为 null=用内置); - 数据节点:
sql/redis/rabbitmq角色各自跑对应run-*.sh; - 备份与 cron 收敛到
cron角色节点,避免多节点重复收卷(实测 cron.daily 全脚本按角色分支设计)。
5.3 多服务 Compose 形态(官方仓库)
官方提供拆好的多服务栈 jhpyle/docassemble-compose(实测仓库结构:services/core、services/docassemble-webapp、services/docassemble-libreoffice、services/docassemble-tesseract、services/docassemble-pandoc + setup.sh 生成 compose 与初始配置模板)。与本文单容器形态的差异:PG/Redis/RabbitMQ 独立容器、持久卷直接挂数据目录,不再依赖「安全关机收卷」机制;适合单机角色拆分仍不够用的规模。选型与部署细节见 《docassemble 1.10.15 Docker Compose 部署指南》 第二章镜像选型。
5.4 缩容
单容器形态的缩容即减负载面:supervisorctl stop 休眠不需要的单元(如不用文档转换可 stop unoserver、不用 NLP 保持 nascent 停止),Web 并发回落到 processes=1;角色化部署则反向合并回 CONTAINERROLE=:all: 单机。数据无需搬迁——backup 卷/数据库始终单点。
六、升级与回滚
6.1 镜像内更新链路(实测脚本与执行)
镜像内置 supervisor 程序 update(实测状态 STOPPED Not started),由 Web 包管理页按需触发;开机链路里 initialize.sh 则按配置调用同一脚本。update.sh 全文实测:
#!/bin/bash
export DA_ROOT="${DA_ROOT:-/usr/share/docassemble}"
export DA_DEFAULT_LOCAL="local3.14"
export DA_ACTIVATE="${DA_PYTHON:-${DA_ROOT}/${DA_DEFAULT_LOCAL}}/bin/activate"
export DA_CONFIG_FILE="${DA_CONFIG:-${DA_ROOT}/config/config.yml}"
source /dev/stdin < <(source "${DA_ACTIVATE}" && python -m docassemble.webapp.read_config "${DA_CONFIG_FILE}")
source "${DA_ACTIVATE}"
export CONTAINERROLE=":${CONTAINERROLE:-all}:"
export HOME=/var/www
export LC_ALL=C
set -- $LOCALE
export LANG=$1
if [ "${DAREADONLYFILESYSTEM:-false}" == "false" ] && [ "${DAALLOWUPDATES:-true}" == "true" ]; then
python -m docassemble.webapp.update "$DA_CONFIG_FILE" check_for_updates
fi
exit 0
两道闸门:DAREADONLYFILESYSTEM=true(只读文件系统模式)或 DAALLOWUPDATES=false 都会跳过更新检查——生产要「不被动升级」,就把 DAALLOWUPDATES 设为 false(实测 config.yml allow updates: true、update on start: true 为出厂默认)。
直接执行 update.sh 实测回显(当前已是 1.10.15 最新,无包变更):
docker exec docassemble-1.10.15-web bash /usr/share/docassemble/webapp/update.sh 2>&1; echo "EXIT=$?"
clear_invalid_package: starting after 1.9073486328125e-06 seconds
clear_invalid_package: finishing after 0.0665886402130127 seconds
clear_invalid_package_auth: starting after 0.06661772727966309 seconds
clear_invalid_package_auth: finishing after 0.0677790641784668 seconds
update: updating with mode check_for_updates after 0.06780123710632324 seconds
check_for_updates: starting after 0.06780576705932617 seconds
check_for_updates: 0.5 after 0.06782364845275879 seconds
check_for_updates: 1 after 0.07367682456970215 seconds
get_installed_distributions: starting after 0.07369685173034668 seconds
WARNING: The directory '/var/www/.cache/pip' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you should use sudo's -H flag.
get_installed_distributions: ending after 0.24893951416015625 seconds
check_for_updates: 2 after 0.24900126457214355 seconds
check_for_updates: 3 after 0.25010204315185547 seconds
(输出节选,实测首尾:步骤打点 4~10 行省略,均为 check_for_updates: N after 0.25x 秒格式)
check_for_updates: 11 after 0.2567605972290039 seconds
check_for_updates: finished uninstalling and installing after 0.2576920986175537 seconds
update: touched wsgi file after 0.2578918933868408 seconds
EXIT=0
解读:check_for_updates 模式只检查 PyPI 上 docassemble 相关包的更新并安装,最后 touched wsgi file——配合 uwsgi.ini 的 touch-reload = docassemble.wsgi 实现免重启热加载。get_installed_distributions 阶段那条 pip cache WARNING 是无害噪音(HOME 被脚本固定为 /var/www),不影响结果。
Web 侧对应入口:/playgroundpackages?project=default(实测 200,<title>Packages</title>)安装/升级扩展包,提交到 /updatepackage 端点执行,本质就是触发上述 update 单元。
6.2 reset:配置/包变更后的生效动作
reset.sh(supervisor 一次性程序)实测逻辑:并行执行 python -m docassemble.webapp.restart(Web 应用)、stop/start websockets、stop rabbitmq→start rabbitmq 与 stop/start celery、celerysingle(后台任务),并按 PIPINDEXURL/PIPEXTRAINDEXURLS/PIPTRUSTEDHOST 写 pip 源配置(内网走私有源时用)。实测执行:
docker exec docassemble-1.10.15-web supervisorctl start reset
# reset: started
随后 supervisorctl status 可见 celery STARTING→RUNNING,uwsgi/nginx 进程号不变(reset 走 touch-reload 热重载,不杀主进程)。改 config.yml、装包、改访谈引擎行为后跑一次 reset 即可。
6.3 镜像级升级(官方推荐主路径)
版本节奏实测(GitHub Releases,查询日 2026-11-01):v1.10.15 发布于 2026-10-29,1.10.7 发布于 2026-08-02——1.10.x 系列约每 2~3 周一版。Docker Hub jhpyle/docassemble tag 实测(经代理查询,官方源直连超时):latest, 1.10.15, 1.10.14, 1.10.13, 1.10.12, 1.10.11, 1.10.10, 1.10.9。
标准升级四步(以实测 tag 列表中的 1.10.14 → 1.10.15 为例;当前环境 latest 即 1.10.15,若锁的是旧 tag,操作相同):
# 1) 先做逻辑备份(见 3.2/3.3),确认 backup 卷健康
# 2) 锁定目标 tag 后拉新镜像
sed -i 's|image: jhpyle/docassemble:1.10.14|image: jhpyle/docassemble:1.10.15|' docker-compose.yml
docker compose pull
# 3) 优雅停机(触发安全收卷,窗口 600s 已在 compose 配置)
docker compose down # 等价 docker stop -t 600 docassemble-1.10.15-web
# 4) 用新镜像重建并巡检
docker compose up -d
docker exec docassemble-1.10.15-web supervisorctl status
curl -s http://localhost:8139/ | grep -oE '<title>[^<]+</title>'
开机时 initialize.sh 会自动把数据库结构升级到新版本(官方 Docker 文档口径:启动模块「ensures that all of the necessary SQL database tables are created if they do not exist, and performs any necessary upgrades using Alembic」),实测库内确有 alembic_version 表(3.2 的 pg_restore -l TOC 首行 TABLE public alembic_version 可见)。升级后首页标题恢复 Default interview(或业务访谈标题)即就绪;首启组件加载实测约 17 分钟,升级重启通常更快(依赖已装),但别在 5 分钟内下结论。
⚠️ 网络说明:查询 Docker Hub tag 与 GitHub Releases 时官方源直连超时,实测改走代理
192.168.1.72:7897成功(HTTP 200);镜像docker pull走宿主 Docker 守护进程既有加速渠道,未发生降级。
6.4 回滚
镜像级回滚是本文采用「锁 tag 而非 latest」的直接收益:
sed -i 's|image: jhpyle/docassemble:1.10.15|image: jhpyle/docassemble:1.10.14|' docker-compose.yml
docker compose up -d # 本地已有 1.10.14 镜像时无需重新 pull
⚠️ 注意:回滚有一个不可自动化的坑——数据库结构降级。新版本启动时 Alembic 会把表结构升到新 schema,回滚旧镜像后旧代码面对新 schema 可能报错。稳妥顺序:升级前做 3.2 的逻辑备份 → 升级验证 → 若需回滚,镜像回滚后用升级前的
pg_dump产物恢复docassemble库(3.3 流程),再supervisorctl start reset。只回滚镜像不回滚数据,仅适用于 schema 未变的补丁版本。
6.5 升级操作清单(实测沉淀)
pg_dump -F c手动备份并pg_restore -l校验(3.2);- 记录当前版本:
/config页脚 +pip show docassemble.base(2.5); - compose 里锁定目标 tag,
docker compose pull; docker compose down等安全收卷(勿强杀,见 3.4);docker compose up -d,观察docker logs -f至各单元 RUNNING;- 巡检:
supervisorctl status、首页标题 200、跑一遍冒烟访谈(部署文档 4.5/十二节的验收序列); - 异常即按 6.4 回滚镜像+数据。
七、故障排查手册
先定位层,再查原因。实测归纳的分层入口:
| 层 | 现象 | 第一现场 |
|---|---|---|
| 容器 | 起不来/反复重启 | docker compose ps、docker logs --tail 50 <容器> |
| 进程 | 部分功能 502 | supervisorctl status(2.1 判读表) |
| Web | 页面报错 | /logs 页或 docassemble.log(2.2 行格式) |
| 访谈 | 打开即报错/卡住 | docassemble.log 按 i=<访谈路径> grep |
| 数据 | 重启后内容回档 | 开机日志 unsafe shutdown detected(3.4) |
实测高频故障速查(处置细节见本文对应小节与「八、常见问题」):
- 整站 5xx/无法访问:先看是否处于启动期(
<title>Docassemble is starting</title>,实测首启约 17 分钟);uwsgi 异常则supervisorctl restart uwsgi,实测 uwsgi.log 尾部出现WSGI app 0 (mountpoint='') ready in 3 seconds为恢复标志。 - 访谈执行错误:
docassemble.log中形如Tried to run _internal["answers"]['ID greeting'] = int('exit') and got error ValueError: invalid literal for int() with base 10: 'exit'的行即引擎侧真实报错(实测样本,2.2);改 YAML 后若错误状态「粘住」,是会话错误缓存作祟——实测错误态存 PGuserdict表(filename=访谈 URL、key=session),DELETE FROM userdict WHERE filename LIKE '%<访谈名>%'后刷新即干净重跑。 - CSRF 400:非浏览器客户端 POST 表单未带
csrf_token时实测日志flask_wtf.csrf.CSRFError: 400 Bad Request: The CSRF token is missing.——脚本化调用要先 GET 取 token。 - 配置改了不生效:
config.yml改动需supervisorctl restart uwsgi或supervisorctl start reset(6.2);环境变量类(DAHOSTNAME 等)只在开机生成时生效,改环境变量要走docker compose up -d重建。 - 数据库连不上/表缺失:确认
main:postgresRUNNING(2.1)→psql手连(2.3)→ reset 时启动模块会补建表与 Alembic 升级(6.3)。
八、常见问题
Q1: 升级后访谈功能异常,怀疑包没更新到位?
A: 镜像级升级(6.3)后开机 initialize 会统一处理;若是在容器里手动 pip 装/升了包,必须 supervisorctl start reset 让 uwsgi/celery/websockets 全部重载(6.2 实测逻辑),只重启 nginx 无效。
Q2: pg_dump 报 Permission denied?
A: backup 目录属 root、postgres 用户不可写(实测 3.2 报错原文)。按官方 cron 同款做法:先 dump 到 postgres 属主的临时目录,再由 root rsync 进 backup。
Q3: 每天备份会不会把磁盘撑爆?
A: 滚动目录按 DABACKUPDAYS(实测 14)天自动清理(3.1 节 cron 脚本摘录末段的 find ... -mtime +${DABACKUPDAYS:-14} -print 清理逻辑实测);files 的 rsync 带 --delete 不会无限堆积。真正要盯的是 files/ 本体增速(附件/生成文档),用 2.4 的 df 巡检设告警。
Q4: 能不能关掉自动更新,完全手动控制版本?
A: 能。compose 环境变量 DAALLOWUPDATES: "false"(对应 config.yml allow updates)即让 update.sh 跳过 check_for_updates(6.1 实测脚本闸门),版本升级全部走 6.3 的镜像级流程。
Q5: 单容器全栈和官方 compose 多服务栈怎么选?
A: 判据在负载与恢复模型:单机/小规模用单容器(备份恢复走 backup 卷,运维面最小);Web/任务/数据要独立扩缩、或不能接受「关机收卷」模式时用 jhpyle/docassemble-compose 拆服务(5.3)。平台定位与选型对比见 《docassemble 1.10.15 介绍与选型指南》。
九、参考链接
- 官方 Docker 文档(升级/角色/备份):https://docassemble.org/docs/docker.html
- 官方配置文档:https://docassemble.org/docs/config.html
- 官方扩展性文档(CONTAINERROLE 角色拆分):https://docassemble.org/docs/scalability.html
- 官方安装文档(Upgrading docassemble 章节):https://docassemble.org/docs/installation.html
- 官方管理文档(Monitor/Logs/包管理页):https://docassemble.org/docs/admin.html
- 多服务 Compose 仓库:https://github.com/jhpyle/docassemble-compose
- GitHub 发布记录:https://github.com/jhpyle/docassemble/releases