Mayan EDMS Docker Compose 部署实战

Mayan EDMS 4.12.2 官方 Docker Compose 部署实战:all_in_one 栈(应用+PostgreSQL+Redis+RabbitMQ)搭建、自动管理员初始化、中文 OCR 语言包实测、资源与数据卷盘点、排障实录,全程逐命令实测。

Mayan EDMSMayan EDMS2026/10/28

Mayan EDMS Docker Compose 部署实战

目标:用 Mayan EDMS 官方 Docker Compose 编排在服务器上部署一套可用的文档管理系统(4.12.2),覆盖官方编排结构解析、环境变量定制、首次启动初始化、管理员账号初始化、中文 OCR 语言包安装与识别实测、资源占用盘点、数据卷持久化与排障实录。本文所有命令与回显均在部署过程中逐条实测。

一、环境信息

  • 操作系统内核:Linux 7.0.0-38-generic(x86_64,uname -r 实测回显)
  • Docker:29.9.2(docker --version 实测回显:Docker version 29.9.2, build a82e528)
  • Docker Compose 插件:v5.6.1(docker compose version 实测回显:Docker Compose version v5.6.1)
  • Mayan EDMS:4.12.2(官方 s4.12 镜像标签;启动横幅与 pip show 双重实证,见第六章;版本溯源见 《Mayan EDMS 介绍与选型指南》)
  • 伴生服务版本(官方编排 pin 值):PostgreSQL 15.17、Redis 7.4.8、RabbitMQ 4.1.8-management(可选 profile:Elasticsearch 9.1.10、Traefik v3.7.9)
  • OCR 引擎:Tesseract 5.5.0(tesseract --version 实测)
  • 部署目录:/opt/data/quzuo/tmp/mayan-edms/compose/(docker-compose.yml、.env、override 文件所在)
  • 宿主服务端口:8140(本机 80 已被占用,映射应用 8000;无占用时可写 80:8000)
  • 独立网段:10.89.58.0/24(显式指定,避开本机已占网段,见排障实录 §10.1)

二、官方编排获取与服务结构

2.1 下载官方编排文件

官方文档《Install with Docker Compose》给出的标准做法是:在一个专用目录中下载官方 docker-compose.yml 与 .env 两个文件,然后 docker compose up --detach。在部署目录执行:

curl https://gitlab.com/mayan-edms/mayan-edms/-/raw/master/docker/docker-compose.yml -O
curl https://gitlab.com/mayan-edms/mayan-edms/-/raw/master/docker/.env -O

两个文件合计约 26 KB(2026-10-28 下载,对应 4.12 系列最新编排)。

2.2 服务清单与 profile 划分

官方编排用 Compose profile 控制启停,解析后服务与镜像对应关系如下(版本号均为编排文件 pin 值):

服务官方镜像 pin角色profile
appmayanedms/mayanedms:s4.12一体化应用:Web(Gunicorn 8000)+ 六类后台任务 worker + 定时调度all_in_one(默认启用)
postgresqlpostgres:15.17元数据库(文档记录/版本/权限/工作流/事件)postgresql(默认启用)
rabbitmqrabbitmq:4.1.8-managementCelery 任务队列(vhost mayan)rabbitmq(默认启用)
redisredis:7.4.8任务结果(db1)/分布式锁(db2)/服务端事件流(db3)redis(默认启用)
elasticsearchelasticsearch:9.1.10可选全文检索后端elasticsearch(默认关闭)
traefiktraefik:v3.7.9可选反向代理/TLS 终结traefik(默认关闭)
frontend同 app拆分部署时的独立 Web 前端extra_frontend/multi_container
worker_a ~ worker_f同 app拆分部署时的六类独立 workerextra_worker_a~extra_worker_f/multi_container
celery_beat同 app拆分部署时的定时调度extra_celery_beat/multi_container
worker_custom_queue同 app自定义队列 worker(读 MAYAN_WORKER_CUSTOM_QUEUE_LIST)extra_worker_custom
setup_or_upgrade同 app独立初始化/升级执行器extra_setup_or_upgrade/multi_container
postgresql-backuppostgres:15.17单次数据库备份任务(pg_dump 写入备份卷)postgresql-backup
cabinet_mirror / index_mirror同 appFUSE 文件系统视图(抽屉/索引镜像)cabinet_mirror/index_mirror

默认 COMPOSE_PROFILES=all_in_one,postgresql,rabbitmq,redis,即最小可用形态只起四个服务。编排文件用 YAML 锚点(x-mayan-container、x-mayan-environment 等)统一复用环境变量、健康检查、日志轮转(json-file,单文件 100m × 3 份)与 restart: unless-stopped 策略,改参数时建议优先动 .env 而不是编排骨架。

三、环境变量定制(.env)

官方 .env 模板约 100 行,生效项 13 个,其余为注释可选项。本次部署在部署目录写入如下定制版 .env(# ===== 分隔之后为实测追加项,其余保持官方默认):

# ===== 官方 .env 模板默认值 =====
COMPOSE_PROJECT_NAME=mayan-edms-412-stack
COMPOSE_PROFILES=all_in_one,postgresql,rabbitmq,redis

# Web 前端端口(宿主 8140 -> 应用 8000)
MAYAN_FRONTEND_HTTP_PORT=8140

# 首次启动自动创建的管理员账号(官方 MAYAN_AUTOADMIN_* 变量)
MAYAN_AUTOADMIN_USERNAME=admin
MAYAN_AUTOADMIN_PASSWORD=q1w2e3r4

# 启动前等待的依赖服务
MAYAN_DOCKER_WAIT="postgresql:5432 rabbitmq:5672 redis:6379"

# 自定义任务队列 worker(默认空)
MAYAN_WORKER_CUSTOM_QUEUE_LIST=

# Traefik 相关(未启用,保持默认空值)
MAYAN_TRAEFIK_LETS_ENCRYPT_EMAIL=
MAYAN_TRAEFIK_EXTERNAL_DOMAIN=
MAYAN_TRAEFIK_DASHBOARD_ENABLE=false
MAYAN_TRAEFIK_DASHBOARD_AUTHENTICATION=''
MAYAN_TRAEFIK_FRONTEND_ENABLE=false
MAYAN_TRAEFIK_RABBITMQ_ENABLE=false
MAYAN_TRAEFIK_LETS_ENCRYPT_DNS_CHALLENGE_PROVIDER=
MAYAN_MIRROR_INDEX_NAME=
MAYAN_MIRROR_CABINET_NAME=

# ===== 实测追加:启动时安装中文 OCR 语言包 =====
MAYAN_APT_INSTALLS=tesseract-ocr-chi-sim

三个关键定制点的说明:

  1. COMPOSE_PROJECT_NAME=mayan-edms-412-stack:项目名会出现在全部数据卷名前缀里(mayan-edms-412-stack_postgres 等),建议带版本语义。注意 Compose 项目名不允许点号,写 4.12 会直接报错,本例用 412(见排障实录 §10.2)。
  2. MAYAN_FRONTEND_HTTP_PORT=8140:官方编排的端口映射模板是 "${MAYAN_FRONTEND_HTTP_PORT:-80}:8000",改这一个变量即可换宿主端口,应用内部始终监听 8000。
  3. MAYAN_AUTOADMIN_USERNAME/PASSWORD:4.12 首次启动会自动创建管理员并生成随机密码显示在登录页;在启动前用这两个变量预设凭据,即可固定为已知密码。首次启动后再改 .env 里的密码不会同步已建账号。

.env 中还有两类值得留意的注释项:安全类(MAYAN_DATABASE_PASSWORD、MAYAN_RABBITMQ_PASSWORD、MAYAN_REDIS_PASSWORD 等,官方注释强调 "Change these before the first run",首启后改这里不同步组件自身密码)与加固类(MAYAN_ALLOWED_HOSTS 配 Django 主机头校验、MAYAN_GUNICORN_BIND_CONTAINER_IP_ONLY 限制监听面)。完整变量表见 《Mayan EDMS 配置参数详解》。

四、独立网段与容器命名(override)

本机同时跑多套自托管栈,为避免网段漂移与名字冲突,新增 docker-compose.override.yml(Compose 会自动合并到主编排):

services:
  app:
    container_name: mayan-4.12-app
  postgresql:
    container_name: mayan-4.12-postgresql
  rabbitmq:
    container_name: mayan-4.12-rabbitmq
  redis:
    container_name: mayan-4.12-redis

networks:
  mayan:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.58.0/24

陷阱记录:本机当时 10.89.57.0/24 已被另一套并行部署栈占用,首启直接失败;改用 10.89.58.0/24 后正常。多栈环境部署前先 docker network inspect 盘点已占网段。

启动前用官方文档推荐的命令核验最终解析结果:

docker compose config --services

实测回显(默认 profile 下应解析出 4 个服务):

app
postgresql
rabbitmq
redis

五、启动与首次初始化

5.1 启动

docker compose up --detach

实测回显(首次启动需先拉取 4 个镜像,合计约 2.4 GB):

[+] Running 8/8
 ✔ Network mayan-edms-412-stack_mayan      Created
 ✔ Volume "mayan-edms-412-stack_app"       Created
 ✔ Volume "mayan-edms-412-stack_postgres"  Created
 ✔ Volume "mayan-edms-412-stack_rabbitmq"  Created
 ✔ Volume "mayan-edms-412-stack_redis"     Created
 ✔ Container mayan-4.12-rabbitmq           Healthy
 ✔ Container mayan-4.12-postgresql         Healthy
 ✔ Container mayan-4.12-redis              Healthy
 ✔ Container mayan-4.12-app                Started

5.2 应用初始化过程

应用启动后先执行官方入口脚本的初始化段,再进入业务进程。首次启动日志的关键序列(docker compose logs app 实测节选):

Starting `entrypoint.sh`.
Executing pre setup script.
Waiting for services.
Connection attempt #1 to: port postgresql:5432; Connected.
Connection attempt #1 to: port rabbitmq:5672; Connected.
Connection attempt #1 to: port redis:6379; Connected.
All services connected.
Executing `update_uid_gid`.
usermod: no changes
Executing `os_package_installs`.
Nothing to install.
Executing `pip_installs`.
Nothing to install.
Building font information cache files.

随后进入数据库迁移与索引初始化(4.12.2 首启迁移量大,这段最长),最后由 supervisor 拉起 8 个业务进程:

mayan-edms-celery-beat           RUNNING   pid 73
mayan-edms-gunicorn              RUNNING   pid 80
mayan-edms-worker_a              RUNNING   pid 74
mayan-edms-worker_b              RUNNING   pid 75
mayan-edms-worker_c              RUNNING   pid 76
mayan-edms-worker_d              RUNNING   pid 77
mayan-edms-worker_e              RUNNING   pid 78
mayan-edms-worker_f              RUNNING   pid 79

(supervisorctl status 实测,均为 RUNNING。)

实测时间线:从 up 完成(依赖服务 Healthy)到 Web 首次可访问(HTTP 302 跳登录页)约 6 分钟(含数据库迁移与索引初始化);后续重启因数据卷已初始化,45 秒左右即可就绪。期间用轮询观察:

curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8140/

初始化完成前连接被拒(000),完成后返回 302。

5.3 版本实证

docker compose exec app /opt/mayan-edms/bin/python -m pip show mayan-edms | head -3

实测回显:

Name: mayan-edms
Version: 4.12.2
Summary: Mayan EDMS

启动横幅同样标注 Mayan EDMS 4.12.2(Copyright 2026 Roberto Rosario,License: GPL 2.0)。

六、首次登录与管理员账号

6.1 自动管理员

本次通过 MAYAN_AUTOADMIN_USERNAME/PASSWORD 预设了 admin / q1w2e3r4。验证账号确实由自动初始化创建:在事件流中能看到首条事件的操作者信息(GET /api/v4/users/1/ 实测回显节选):

{"username": "admin", "email": "autoadmin@example.com", "is_active": true, ...}

邮箱 autoadmin@example.com 正是自动管理员模块的默认落款(对应设置 AUTOADMIN_EMAIL)。若不预设变量,4.12 会在首次打开登录页时显示随机生成的初始密码,登录后应立即改密。

浏览器访问 http://<服务器地址>:8140/,用 admin / q1w2e3r4 登录即进入主界面。系统自带一个 Default 文档类型与一个 Default 浏览器上传源,开箱即可上传第一份文档。

6.2 初始化自带对象

默认对象盘点(API 实测):

  • 文档类型:Default(id 1,文件名生成器 uuid,回收站保留 30 天)
  • 上传源:Default(类型 SourceBackendWebForm,浏览器表单上传)
  • 空 API Token 状态:需先为用户创建 Token(见 《Mayan EDMS 常用命令与运维实战》第三章)

七、中文 OCR 语言包实测

7.1 默认语言包盘点

docker compose exec app tesseract --list-langs

实测回显(默认镜像仅两个语言包):

List of available languages in "/usr/share/tesseract-ocr/5/tessdata/" (2):
eng
osd

中文文档直接入库会因缺包无法正确识别。

7.2 用 MAYAN_APT_INSTALLS 安装中文包

官方入口脚本内置运行时扩展机制:.env 中设置 MAYAN_APT_INSTALLS=tesseract-ocr-chi-sim 后重建服务(docker compose up -d),日志出现 apt 安装序列(Debian trixie 源),完成后复查语言包:

List of available languages in "/usr/share/tesseract-ocr/5/tessdata/" (3):
chi_sim
eng
osd

7.3 端到端识别实测

生成一张含中文的测试图(宿主机 PIL + Noto Serif CJK 字体),经 API 上传为文档「QZ-2026-0429 中文采购合同」。第一次识别输出乱码——根因不是语言包缺失,而是 Mayan 的 OCR 语言取自文档的 language 属性(默认 eng),用英文模型跑中文图必然乱码。

修正动作:把该文档的 language 改为 chi_sim 后重新提交 OCR,识别结果逐行比对:

技术文档 OCR 中文识别测试
合同编号 : QZ-2026-0429
项目金额 : 一百二十万元整
供应商 : 曲作贸易有限公司

四行全部正确。随后全文检索「曲作贸易」与「QZ-2026-0429」均命中该文档(count=1)。完整的 API 调用序列与回显见运维实战篇。

八、资源占用与容量盘点

OCR 处理进行中的瞬时资源快照(docker stats --no-stream 实测):

服务内存占用CPU
mayan-4.12-app3.728 GiB45.55%
mayan-4.12-postgresql78.57 MiB27.24%
mayan-4.12-rabbitmq211 MiB3.27%
mayan-4.12-redis11.86 MiB0.23%

应用是内存大头(Gunicorn 3 个 gevent worker + 6 类 Celery worker 全在一体内),OCR 峰值接近官方「最低 4 GB 内存」的红线;官方对基础部署的推荐配置是 16 GB 内存 / 8 核 / SSD。内存小于 4 GB 的机器不建议跑默认形态,可考虑拆分部署(multi_container profile)或只做轻量归档。

数据卷盘点(首次初始化完成后实测):

卷名容量内容
mayan-edms-412-stack_app828 KB应用数据:document_storage/(文档文件)、config.yml(设置快照)、预览缓存
mayan-edms-412-stack_postgres72.1 MBPostgreSQL 数据目录
mayan-edms-412-stack_rabbitmq1.0 MB队列数据(mnesia)
mayan-edms-412-stack_redis4 KB锁/结果/事件流(无持久化策略)
mayan-edms-412-stack_postgres-initdb—数据库初始化脚本挂载点(空)

备份操作(pg_dump + 应用卷打包实测命令)见 《Mayan EDMS 常用命令与运维实战》。

九、升级与回退路径

官方升级思路(文档站《Upgrading》章 + 编排内置 setup_or_upgrade 服务):

  1. 备份全部数据卷与数据库(先备份,再动手)。
  2. .env 中将 MAYAN_DOCKER_IMAGE_TAG 指向新版本标签(默认跟随 s4.12 系列标签滚动)。
  3. docker compose down 后重新 docker compose up --detach,应用启动时自动检测版本差异并执行数据库迁移(common_perform_upgrade)。
  4. 回退需回滚镜像标签并恢复备份卷,因此升级前备份是硬要求。

十、排障实录

10.1 网段冲突导致启动失败

现象:docker compose up 报网络创建失败,提示地址池重叠。 排查:docker network inspect 发现 10.89.57.0/24 已被本机另一套并行栈占用。 解决:override 中改用空闲的 10.89.58.0/24。多栈机器部署前应先盘点已占网段。

10.2 项目名含点号

现象:COMPOSE_PROJECT_NAME=mayan-edms-4.12-stack 时 docker compose config 直接报 invalid project name。 解决:Compose 项目名只允许字母数字、连字符与下划线,改为 mayan-edms-412-stack。

10.3 首次启动 Web 迟迟不可访问

现象:up 完成后 6 分钟内访问 8140 均无响应。 原因:首启要跑完整数据库迁移与索引初始化,属于正常现象;判断依据是日志中 supervisor 8 个进程全部 RUNNING 且 HTTP 探测从 000 变为 302。 教训:不要在首启阶段反复重启服务,等就绪即可。

10.4 中文 OCR 乱码(两段式根因)

第一层:镜像默认只有 eng/osd 语言包,中文识别必然失败——用 MAYAN_APT_INSTALLS=tesseract-ocr-chi-sim 补包。 第二层:补包后仍乱码,因为识别语言取自文档的 language 属性(默认 eng)——把文档 language 改为 chi_sim 并重提 OCR 后识别全对。 教训:OCR 正确性 = 语言包存在 × 文档 language 匹配 × OCR 任务重新提交,三者缺一不可。

10.5 删除文件导致活动版本页面丢失

实测中误删了文档的文件记录,导致其派生的活动版本页面数归零(版本还在、页面没了,OCR 内容随之消失)。文档系统中「文件→版本→页面→OCR 内容」是级联依赖,清理重复上传的文件时应先核对版本归属。

十一、清理与卸载

docker compose down          # 停止并删除四个服务与网络,保留全部数据卷
docker compose down -v       # 连同数据卷一起删除(文档数据永久丢失,慎用)

本文实验环境在收尾时已执行完整 down -v 清理,镜像可按需 docker rmi 释放。

十二、参考链接