夜雨聆风学习资料网

ARTICLE · 1341424

老板要文档清单,你还在翻三个人微信收藏

老板要文档清单,你还在翻三个人微信收藏

开源运维

2026.11.10

老板要文档清单

你还在翻三个人微信收藏?

运维手册散在三个人的微信收藏里,SOP 存在某个同事的本地 Word,值班表是 Excel 截图——人一离职,文档跟着蒸发。想上 Confluence,按人头报预算,财务那关先卡住;想用 Notion,数据出境和合规又过不去。这是国内中小团队最典型的文档困境:不是没有工具,是没有一个自己能管、按空间分权限、还带版本历史的地方。

Docmost 就是冲这个场景来的。GitHub 上 2.2 万星,官方定位很直白:开源的协作 Wiki 和文档软件,Confluence 与 Notion 的替代品。技术栈是 NestJS 后端 + PostgreSQL 存正文与元数据 + Redis 做缓存和实时协作的适配器,三个容器起步,AGPL-3.0 许可,商用自建不花钱。下面这份教程按真实部署命令走,参数原样照抄即可,坑也一并写清楚。

壹

它到底解决什么

CHAPTER 01

先别急着敲命令,判断一下这东西对不对你的胃口。三个最典型的落地场景:

运维 SOP 与故障处置手册。 按空间切开——机房、网络、系统各一个 Space,每个空间下按"日常巡检 / 故障处置 / 变更流程"建页面树。页面历史会记录谁在什么时候改了哪一段,值班同事照着 SOP 执行时发现步骤过时,直接改,改完留痕,下次复盘能翻到是谁、为什么改。这比共享盘里 SOP_final_v3_最终版_真的最终.docx 靠谱得多。

部门知识库。 空间 + 组 + 权限三层模型。财务的方案书放进财务空间,运维账号看不到;技术部的架构决策记录放技术空间,全员可读不可写。权限粒度到页面级,私有页面只有作者和被授权的人能进。这一层是 Confluence 收费的核心,Docmost 开源版直接给。

技术文档带图。 页面里能直接嵌 draw.io、Excalidraw、Mermaid 三种图,架构图、流程图、时序图不用截图贴进来,改图就是改文档。评审意见用评论挂在具体段落旁边,不用在群里刷"第 3 段那个接口地址是不是错了"。

贰

部署:一份 compose 起三个容器

CHAPTER 02

前置条件四条,缺一不可:Linux 主机、Docker 24 以上、装了 compose 插件、3000 端口空着。先验一遍:

bash

docker --version && docker compose version

配置目录只放 compose 文件和 .env,数据卷全交给 Docker 管,别自己 mkdir 数据目录再 bind mount,权限和 SELinux 会教你做人。

bash

mkdir -p /opt/docmost && cd /opt/docmost

两个密钥必须现场生成。APP_SECRET 程序启动时强校验,必须 32 位以上;DB_PASSWORD 给 Postgres 用:

bash

echo "APP_SECRET=$(openssl rand -hex 32)" > .env

echo "DB_PASSWORD=$(openssl rand -hex 16)" >> .env

然后写 compose。三个服务、三个命名卷,一个都不能少:

bash

cat > docker-compose.yml <<'EOF'

services:

 docmost:

  image: docmost/docmost:latest

# 生产环境换成 Releases 里的版本号,本文对应 v0.97.0

  depends_on: [db, redis]

  environment:

   APP_URL: 'http://192.168.6.10:3000'    # 必须写成同事真正访问的地址(反代后填 https 域名)

   APP_SECRET: '${APP_SECRET}'

   DATABASE_URL: 'postgresql://docmost:${DB_PASSWORD}@db:5432/docmost'

   REDIS_URL: 'redis://redis:6379'

   DISABLE_TELEMETRY: 'true'

   FILE_UPLOAD_SIZE_LIMIT: '50mb'

   TZ: 'Asia/Shanghai'

  ports:

   - "3000:3000"

  restart: unless-stopped

  volumes:

   - docmost_data:/app/data/storage

 db:

  image: postgres:18

  environment:

   POSTGRES_DB: docmost

   POSTGRES_USER: docmost

   POSTGRES_PASSWORD: '${DB_PASSWORD}'

   TZ: 'Asia/Shanghai'

  restart: unless-stopped

  volumes:

   - db_data:/var/lib/postgresql

# PG18 官方镜像的数据目录,别抄旧教程的 /var/lib/postgresql/data

 redis:

  image: redis:8

  command: ["redis-server", "--appendonly", "yes", "--maxmemory-policy", "noeviction"]

  restart: unless-stopped

  volumes:

   - redis_data:/data

volumes:

 docmost_data:

 db_data:

 redis_data:

EOF

逐段说几个关键点。APP_URL 是全系统绝对地址的源头,邀请邮件链接、附件下载地址、页面里生成的绝对 URL 全从这来,必须写成同事浏览器里真正敲的地址,反代上 https 之后改成域名。DATABASE_URL 里的 ${DB_PASSWORD} 由 compose 从 .env 插值,所以 .env 和 compose 必须在同一目录。三个卷各司其职:docmost_data 挂 /app/data/storage 存附件和上传的图,db_data 挂 PG18 的数据目录,redis_data 存 AOF。注意 PG18 官方镜像的数据目录已经变成 /var/lib/postgresql(下面是带版本号的子目录),老教程里的 /var/lib/postgresql/data 挂上去等于把数据写进容器可写层。

拉起三个容器,首次要拉镜像加初始化 Postgres,等十几秒:

bash

docker compose up -d

三条验证,一条都不能省:

bash

docker compose ps

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

docker compose logs --tail 5 docmost

预期是三个容器 Up、首页返回 200、日志末尾出现 Nest application successfully started。任何一条不对,先看 docker compose logs docmost 有没有 The Environment variables has failed the following validations。

三条验证命令跑完的输出:三个容器 Up、首页 200、Nest 已启动

叁

第一次打开:建工作区只有一次机会

CHAPTER 03

浏览器访问 http://192.168.6.10:3000,会进 setup 页,填工作区名称、管理员邮箱和密码。这个接口只在一个工作区都不存在时可用——服务端 SetupGuard 的判据就是 workspace 数量,建完再访问会直接回 workspace setup already completed,没有第二次机会。所以工作区名想好再填,管理员邮箱用一个能收信的。

想让邀请邮件正常发出去,得配 SMTP;不配的话就在成员管理里复制邀请链接手动发微信。注意邀请链接会过期,发出去催着点。

打开首页:左边是空间和页面树,中间是页面内容,右上角搜索与成员管理

肆

把文档搬进来:空间、组、权限怎么划

CHAPTER 04

进来之后先划结构,别上来就写。Space 对应部门或项目,一个空间一棵页面树;Group 管人,把"运维组""财务组"建好,成员按组授权;页面可以设私有,也可以整空间公开只读。这套模型撑住几十人的团队绰绰有余。

页面历史与版本回滚是默认能力,改错了随时退。附件和图片落在 docmost_data 卷的 /app/data/storage 下,所以备份的时候这个卷和数据库一样重要。搜索默认走数据库全文索引,文档量级到几千页以内够用;再大就上 Typesense,设 SEARCH_DRIVER=typesense 并补上对应连接参数。

写页面的样子:正文里直接插表格、代码块、画图和评论,右侧能看到页面历史

伍

反代、备份与升级

CHAPTER 05

上生产基本都要 Nginx 反代加 https。三个必须配对的参数:

WebSocket 升级头。 实时协作走 socket.io(服务端 4.8 + Redis adapter),不是普通 HTTP。Nginx 只写 proxy_pass 的话,单人编辑正常,两个人同时改一页就露馅——看不到对方光标、改动不同步、标题偶发回滚。要 proxy_http_version 1.1、透传 Upgrade 和 Connection 两个头、proxy_read_timeout 给到 600 以上,别用默认 60s。

`APP_URL` 改成实际域名(含 https)。 改完必须 docker compose up -d 重建容器才生效,reload nginx 没用。

`client_max_body_size` 要 ≥ `FILE_UPLOAD_SIZE_LIMIT`。 应用侧默认 50mb,Nginx 默认只有 1M,传十几页扫描件时浏览器先失败,docmost 日志里干干净净——请求根本没到应用,要去 Nginx 的 error.log 里才找得到 413。两处一起调大再 reload。

备份是两样东西,缺一个都不算备份:pg_dump 导库 + 打包 docmost_data 卷(或者改用 STORAGE_DRIVER=s3 上对象存储)。只做 dump 的话,恢复后每篇文档的图全是裂的。两个备份放同一天同一批,落到异地。

升级流程固定:先 dump → 改 compose 里的镜像 tag 到 Releases 里的版本号 → docker compose pull && docker compose up -d。Postgres 别跨大版本直接换 tag,18 的数据 19 读不了,要升就走 dump → 换镜像 → restore。

要服务端导出 PDF 得另起一个 Gotenberg 容器,把 GOTENBERG_URL 填进去;纯内网还要画图的话,DRAWIO_URL 留空会走公网 diagrams.net 的嵌入地址,内网机器打不开,得自己再起 drawio 容器。

陆

几个必坑

CHAPTER 06

⚠ 避坑 · `APP_SECRET` 不换成…

APP_SECRET 不换成 32 位以上随机值,或者干脆留着示例里的 REPLACE_WITH_LONG_SECRET,容器启动校验直接 exit(1),屏幕上只有一行 The Environment variables has failed the following validations 加一段 JSON,看着像镜像坏了其实是自己没改。更麻烦的是上线之后再换,之前签发的 JWT 全部失效(JWT_TOKEN_EXPIRES_IN 默认 30d),全公司被踢下线重登。正确做法:上线前就定好,存进密钥库,别写在 compose 里提交 Git。

⚠ 避坑 · `APP_URL` 照抄成 `h…

APP_URL 照抄成 http://localhost:3000,登录能用、写文档也能用,但邀请邮件里的链接、页面里生成的绝对地址、附件下载链接全指回 localhost,同事点开是打不开的本机地址,还以为是权限问题查半天。正确做法:填同事真正访问的地址,反代上 https 之后写实际域名并重建容器。

⚠ 避坑 · Nginx 反代只配 `prox…

Nginx 反代只配 proxy_pass、没转发 WebSocket 升级头,单人编辑完全正常,两个人同时改一页就出问题——看不到对方光标、改动不同步、标题偶发回滚。正确做法:proxy_http_version 1.1、透传 Upgrade 与 Connection、proxy_read_timeout 给到 600 以上。

⚠ 避坑 · 备份只做了 `pg_dump`

页面正文在库里,附件和上传的图在 docmost_data 卷的 /app/data/storage,dump 里一个都没有,恢复后每篇文档的图全是裂的。正确做法:导库 + 打包 storage 卷(或改用 S3)两样一起备。

⚠ 避坑 · postgres 的卷路径照抄老…

postgres 的卷路径照抄老教程写成 /var/lib/postgresql/data,PG18 官方镜像的数据目录已经是 /var/lib/postgresql,挂错等于把数据写进容器可写层,容器一重建、一次 compose down -v 就是全新空库。正确做法:按本文的路径挂,且别跨大版本直接换 tag。

⚠ 避坑 · Redis 用 `noevict…

Redis 用 noeviction 又没设 maxmemory,文档一多、并发协作一上来内存吃满,写命令直接失败,表现是页面能打开、改完不保存、光标不出现,而 docmost 容器日志干干净净。正确做法:给 redis 配 maxmemory 并盯 used_memory,或者 redis 单独一台,别和别的服务挤。

⚠ 避坑 · 企业版功能别当免费功能规划

AI 对话、API Key、MFA 二次验证、页面审批/验证、SSO 单点登录都在 ee 目录下,需要商业授权,开源版点开就是提示升级。采购前先确认这几个是不是硬需求,别等装完给老板演示时才发现。

柒

速查表 · 截图存手机

CHAPTER 07

bash

# 0. 前置:Linux + Docker 24 以上 + compose 插件,3000 端口空着

docker --version && docker compose version

# 1. 配置目录:数据卷交给 docker 管,这里只放 compose 和 .env

mkdir -p /opt/docmost && cd /opt/docmost

# 2. 两个密钥:APP_SECRET 必须 32 位以上,程序启动时会强校验

echo "APP_SECRET=$(openssl rand -hex 32)" > .env

echo "DB_PASSWORD=$(openssl rand -hex 16)" >> .env

# 3. 写 compose:docmost + postgres:18 + redis:8,三个命名卷一个都不能少

cat > docker-compose.yml <<'EOF'

services:

 docmost:

  image: docmost/docmost:latest

# 生产环境换成 Releases 里的版本号,本文对应 v0.97.0

  depends_on: [db, redis]

  environment:

   APP_URL: 'http://192.168.6.10:3000'    # 必须写成同事真正访问的地址(反代后填 https 域名)

   APP_SECRET: '${APP_SECRET}'

   DATABASE_URL: 'postgresql://docmost:${DB_PASSWORD}@db:5432/docmost'

   REDIS_URL: 'redis://redis:6379'

   DISABLE_TELEMETRY: 'true'

   FILE_UPLOAD_SIZE_LIMIT: '50mb'

   TZ: 'Asia/Shanghai'

  ports:

   - "3000:3000"

  restart: unless-stopped

  volumes:

   - docmost_data:/app/data/storage

 db:

  image: postgres:18

  environment:

   POSTGRES_DB: docmost

   POSTGRES_USER: docmost

   POSTGRES_PASSWORD: '${DB_PASSWORD}'

   TZ: 'Asia/Shanghai'

  restart: unless-stopped

  volumes:

   - db_data:/var/lib/postgresql

# PG18 官方镜像的数据目录,别抄旧教程的 /var/lib/postgresql/data

 redis:

  image: redis:8

  command: ["redis-server", "--appendonly", "yes", "--maxmemory-policy", "noeviction"]

  restart: unless-stopped

  volumes:

   - redis_data:/data

volumes:

 docmost_data:

 db_data:

 redis_data:

EOF

# 4. 拉起三个容器(首次要拉镜像 + 初始化 Postgres,等十几秒)

docker compose up -d

# 5. 验证(图 1):三个容器 Up、首页 200、日志里 Nest 已启动

docker compose ps

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

docker compose logs --tail 5 docmost

验证命令
通过标准
cd /opt/docmost && docker compose ps
docmost-docmost-1   docmost/docmost:latest  docmost    Up 2
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/
200
docker compose logs --tail 3 docmost
[Nest] 1  - 11/10/2026, 7:12:03 PM  LOG [NestApplication] Ne

排错顺序:

1

APP_SECRET 不换成 32 位以上随机值(或者干脆留着示例里的 REPL…(详见避坑段)

2

APP_URL 照抄成 http://localhost:3000:登录能用、写…(详见避坑段)

3

Nginx 反代只配了 proxy_pass,没转发 WebSocket 升级头…(详见避坑段)

终

写在最后

SUMMARY

Docmost 的价值不在功能多,在于它把 Confluence 最贵的那部分——空间权限、版本历史、实时协作——用三个容器和一份 compose 交到你手上。部署成本半小时,运维成本取决于你有没有认真做备份和反代。上线前把 `APP_SECRET` 和 `APP_URL` 定死,上线后把 pg_dump 和 storage 卷绑成同一个备份任务,这两件事做对,剩下的就是往里填文档了。

🍵

熊大大 · 小茶馆掌柜

一线踩坑十余年,专治各种「网上都说行,生产就是不行」。

觉得这篇有用,文末右下角的「赞」和「在看」点一下,转发给需要的人。

#文档管理#开源运维#知识沉淀

THANKS FOR READING · 下期再会

我是熊大大,在机房和终端之间泡了十年茶。

如果你觉得今天这篇有收获,欢迎点赞、在看、转发三连,我们下篇见。

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料