尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

docmost 私有化部署指南:用 Docker Compose 搭建轻量级团队 Wiki

docmost 私有化部署指南:用 Docker Compose 搭建轻量级团队 Wiki 团队文档从十个人开始膨胀之后你就会发现“找个文件”变成了一场玄学。钉钉群里传的版本、网盘里改了三遍的 doc、某位同事桌面上那个“最终版(2).docx”每一份都长得像正经文档每一份又都不是最终版。要解决这个问题常规思路是上 Confluence但那个价格对小团队不太友好部署起来也重。另一条路是今天这篇的主角docmost一款开源的协作 wiki 和文档管理软件自托管、有中文界面、支持实时协作跑起来非常轻快。我前后折腾了两个晚上把它部署到了内网服务器上顺手把过程、踩过的坑和最终选定的配置完整记录下来给想搞私有化文档平台的朋友做个参考。1. docmost 是什么以及为什么我要选它先花点时间把 docmost 这个项目交代清楚。它是 GitHub 上的开源知识库项目MIT 协议定位是 Confluence 和 Notion 的轻量替代品。功能上覆盖了团队文档管理最核心的几个点无限层级页面和嵌套空间、多人实时协同编辑、页面版本历史、评论讨论、全文检索、精细的权限管理以及 Markdown 和 LaTeX 数学公式支持。对技术团队来说还内置了代码块高亮、图表绘制和 draw.io 白板嵌入能力开发文档、接口文档、运维手册都能直接在平台内写完、整理完、检索到。我选它而不是 Notion 或语雀核心原因只有两个字可控。Notion 用起来确实顺手但页面和数据全在别人服务器上团队内部方案、客户信息这类敏感内容放上去合规和保密这一关就过不去。docmost 部署在自己服务器上数据、备份、权限、更新节奏完全自己说了算这才是真正的私有化知识库。另外一点是重量级差异。我踩过 Confluence 的坑它在 4G 内存的服务器上跑起来像在爬光是晋级的 Java 进程就能把 CPU 吃掉一大半。docmost 这边是 Node.js PostgreSQL Redis 的经典组合资源占用要克制得多。实测在 2C2G 的云服务器上docmost 主进程 Postgres Redis 三个容器加起来也就占 600M 左右内存日常使用不会对同机房的其它业务产生明显挤压。还有一个常常被忽略的点docmost 的界面非常接近 Notion 的操作体验块级编辑器、Slash 命令、拖拽排版团队成员迁移成本极低。我带项目组的同事试用时几乎没有人需要额外学习半天之内文档就从飞书迁过去了。2. 部署前的环境准备与配置选型2.1 服务器要求到底能压到多低docmost 官方文档给的建议是 1C1G 起步但我不建议这么抠。原因很简单PostgreSQL 和 Redis 这两个基础组件本身就吃内存Robust 运行至少要留出 swap 空间。按我个人经验2C2G 是性价比非常高的平衡点4G 内存则可以起飞。存储方面主要看你们团队文档量和附件上传量如果打算长期沉淀技术文档建议系统盘至少留出 20G 可用空间。网络环境这块内网部署只需要能访问本机端口就行不需要公网 IP。但如果你想要外网访问比如出差时查资料就需要一台公网服务器或者在内网网关做端口转发。我个人建议的做法是内网服务器做主力存储用 Nginx 反代对外暴露如果团队规模不大直接用带 SSL 的域名反代会更省事。证书和域名这块下文第 4 节会展开。2.2 操作系统和软件依赖我部署用的是一台 Ubuntu 22.04 LTS这也是官方文档明确支持的发行版。Debian 12 也实测没问题。系统层面只需要把 Docker 和 Docker Compose 装好这也是 docmost 最省心的部署方式。它的官方镜像同时发布了 docker hub 版本和 ghcr 版本如果你拉镜像慢可以替换成 docker hub 的 docmost/docmost 镜像或者配置 registry mirror。完整的依赖清单如下Docker Engine 20.10Docker Compose v2docker compose 子命令方式Git用于拉取部署配置仓库OpenSSL生成 APP_SECRET 用一般在系统里自带Nginx可选做反向代理时用Docker 的安装我不过多重复直接官方脚本一把梭即可。安装完确认一下docker compose version能用版本太老的话建议升级。2.3 数据目录和域名规划正式部署前先把目录规划好这个环节跳过会导致后续备份很痛苦。我在 /opt 下建了一个 docmost 目录所有配套子目录都集中在里面/opt/docmost ├── docker-compose.yml ├── .env ├── data/ # docmost 应用数据上传文件等 ├── pgdata/ # PostgreSQL 数据目录 └── redisdata/ # Redis 持久化目录域名方面我没用 IP 直连给知识库单独分配了一个子域名 docs.example.com。好处是以后换服务器、加 SSL、配置 SSO 都不用返工。如果你实在没有域名也可以先用 IP 端口方式验证但正式投入使用前建议补上。3. Docker Compose 快速部署完整流程3.1 拉取部署文件和关键配置docmost 官方提供了一个 compose 仓库里面预置了 docker-compose.yml 和 .env 模板。我建议不要直接 clone 下来就跑先看一遍里面的服务定义再按自己需求改。目前最新主版本用的是 0.8.x我这里以 0.8 为例镜像的版本号可以随时在官方 GitHub Releases 页面对照。容器编排上总共有三个服务docmost应用主服务、postgres数据库、redis缓存/协作服务。如果只是本地评估也可以让 docmost 内置 SQLite不用 Postgres但正式团队使用我还是强烈建议用 Postgres并发协作、全文检索都强得多。核心配置在 .env 文件里需要改的地方也不多APP_URLhttps://docs.example.com APP_SECRET$(openssl rand -hex 32) POSTGRES_HOSTpostgres POSTGRES_PORT5432 POSTGRES_DBdocmost POSTGRES_USERdocmost POSTGRES_PASSWORD这里换成强密码 REDIS_HOSTredis REDIS_PORT6379APP_URL 这个变量非常关键它直接决定了平台生成链接、邮件通知时用的基础地址。如果这里配成http://localhost:3000后面别人收到分享链接打开就是乱套的。APP_SECRET 是用来给会话加密的密钥不能随便填几个字符务必用openssl rand -hex 32生成。docker-compose.yml 里我改动过的部分如下核心是把三个数据目录都挂到了宿主机的持久化路径上容器删除重建后数据不丢services: docmost: image: docmost/docmost:0.8.1 restart: unless-stopped depends_on: - postgres - redis environment: APP_URL: ${APP_URL} APP_SECRET: ${APP_SECRET} DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?schemapublic REDIS_URL: redis://${REDIS_HOST}:${REDIS_PORT} volumes: - ./data:/app/data/storage ports: - 127.0.0.1:3000:3000 postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - ./pgdata:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine restart: unless-stopped command: redis-server --appendonly yes volumes: - ./redisdata:/data healthcheck: test: [CMD, redis-cli, ping] interval: 10s timeout: 3s retries: 5注意端口映射这里我特意只绑定了 127.0.0.1:3000也就是说 docmost 默认只允许本机访问。后面走 Nginx 反代让外部流量进来这样可以少暴露一层攻击面。3.2 初始化数据库与首次启动配置改完后先拉镜像再启动docker compose pull docker compose up -d第一次启动时 docmost 会自动执行数据库迁移创建表结构和初始数据。这一步不要急着打开页面先看容器日志确认迁移跑完docker compose logs -f docmost看到Server is listening或类似日志后说明应用已经起来了。这时候访问http://127.0.0.1:3000浏览器会自动跳转到初始化向导要求创建一个管理员账号和站点名称。这里有个细节管理员账号创建完成后平台会引导你创建第一个空间Space。空间相当于顶级文档目录你可以为不同部门建不同空间每个空间内部再按页面层级组织文档。权限上空间可以设置公开可见、仅成员可见、私有等模式初始阶段建议先建一个“全员知识库”空间把公共文档都放进去再按需建各部门专用空间。3.3 验证核心功能是否正常启动完成后我按下面的清单逐项验证过推荐你也照着测一遍创建页面、写入中文标题和正文确认没有乱码两个浏览器同时打开同一篇文档确认实时协作光标和内容同步正常上传一个 5MB 的图片/附件确认默认上传限制没有被卡住搜索一篇刚创建的文档确认全文索引跑得通打开页面左下角设置确认邮件服务或 SMTP 配置入口存在先不配也行如果协作编辑时状态不正常大概率是后面讲的 WebSocket 代理问题不要急着怀疑软件本身往下看第 4 节。4. 接入 Nginx 反向代理和 HTTPS4.1 为什么要做反向代理Docker Compose 跑起来之后应用已经能通过本机 3000 端口访问了。但直接拿 3000 端口给团队用有点粗糙端口号不好记也没有 SSLUpdate 传输内容裸奔。更合理的方式是在前面放一个 Nginx 反向代理统一收口 80/443 进来的流量转发给 docmost同时把 HTTP/1.1 升级、WebSocket 支持这类细节一并处理好。如果你需要外网访问反向代理这层更是必须的。它会负责终结 TLS、隐藏内部容器网络结构将来要在多个应用间共享一台服务器时通过不同的 server_name 做分流也非常方便。4.2 Nginx 配置和 WebSocket 关键点直接给一份我实测可用的 Nginx server 配置。假设你的域名是 docs.example.com后端是 127.0.0.1:3000server { listen 80; server_name docs.example.com; client_max_body_size 100m; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }这里最容易翻车的是最后两行Upgrade和Connection。docmost 的实时协作和在线状态推送依赖 WebSocket 长连接Nginx 默认的 HTTP 代理不会转发 Upgrade 消息导致页面看起来能打开但协作编辑、光标同步全部失效。我第一次部署时就是漏了这两行两个浏览器同时开文档死活看不到对方的光标后来翻浏览器控制台的 WebSocket 连接错误才定位到问题。如果是同一个 Nginx 上还要托管其它服务注意不同 server_name 之间要写好 ssl 证书路径别串了。另外client_max_body_size建议设大一点docmost 默认上传限制是 100MB 左右Nginx 默认的 1MB 会直接挡掉大附件的上传我设成了 100m跟应用层保持一致。HTTPS 证书申请我用的 ACME 方式自动续期Certbot 一键签发crontab 里挂上续期命令。这里提一下证书机构或签发工具的选型按你们已有基础设施来就行比如在阿里云 DNS 上做自动验证也比较常见。最重要的是保证证书到期前能自动续别让团队某天早上打开页面看到大红叉。4.3 防火墙和安全策略反代上线后建议把宿主机防火墙规则收紧对外只放行 80 和 4433000 端口保持只允许本机访问即可。Ufw 命令大致如下ufw default deny incoming ufw allow 80/tcp ufw allow 443/tcp ufw allow OpenSSH ufw enable容器层面docmost 进程默认不启用注册功能管理员邀请成员才可加入这点很稳。日常使用中建议关闭公开注册入口只在管理后台手动邀请。如果后续接入了 SMTP 邮件服务邀请链接是自动发到邮箱的流程更正式。5. 数据备份、升级和日常巡检5.1 备份策略怎么定才不后悔自托管的平台最怕的就是数据丢失。docmost 的业务数据分布在三处PostgreSQL 的数据库表、宿主机./data目录下的上传附件、Redis 里的协作状态缓存。前两个是核心Redis 数据丢了最多丢一点临时会话状态可重启恢复不用强求。我写了一个每晚 3 点跑的备份脚本思路是分别用pg_dump输出数据库快照用tar打包应用数据然后一起丢到独立的备份目录。核心逻辑简化如下#!/bin/bash BACKUP_DIR/backup/docmost DATE$(date %Y%m%d_%H%M) docker compose exec -T postgres pg_dump -U docmost docmost $BACKUP_DIR/docmost_db_$DATE.sql tar czf $BACKUP_DIR/docmost_data_$DATE.tar.gz -C /opt/docmost data find $BACKUP_DIR -name *.sql -o -name *.tar.gz -mtime 30 -delete脚本里最后一行是保留 30 天轮转掉老备份。备份落到本地磁盘只是第一步有条件的话建议再 rsync 到另一台机器或者对象存储否则整个服务器磁盘坏掉时备份也一起没了。恢复流程我也建议实际演练一次别等灾难来了才第一次跑。步骤基本是停掉 docmost 容器、清掉 pgdata 并重新初始化、用psql恢复 SQL 文件、把 data 目录解压回去、重新docker compose up -d。我团队里保留着一个每月一次的“备份恢复演练”惯例知道怎么恢复和能恢复是两码事。5.2 版本升级的具体操作docmost 迭代节奏还是挺快的新版本经常带来功能增补和 bug 修复。我的升级流程是先读官方 Release Notes确认没有破坏性数据库迁移再按下面四步操作先跑备份脚本确认备份文件已生成docker compose pull拉取最新镜像docker compose up -d重建容器观察日志确认数据库迁移完成页面能正常响应升级过程中最容易忽略的是“老版本镜像还留着”这件事。Compose 默认会保留旧镜像如果你想回滚还要记住当前版本 tag。方法很简单升级前先docker compose ps --format table {{.Image}}记录一下镜像名和 tag回滚时再手动指定旧 tag 重新up -d即可。我升级遇到过两次小问题都是数据库迁移耗时比预期长导致前端短暂报 503。这种一般等一两分钟自动恢复不用慌。真正要注意的是生产环境数据库文件很大时比如几个 G 的文档附件迁移期间 I/O 压力会比较大有条件的话挑业务低峰期升级。5.3 日常巡检看哪些指标平台跑起来后日常维护成本其实很低我给自己定了一个“只做三件事”的巡检清单看磁盘df -h数据盘使用率超过 70% 就提前规划清理或扩容看容器状态docker compose ps确认三个服务都是 Up不处于 Restarting看资源占用docker stats --no-stream盯着 docmost 容器的内存曲线接近 1G 说明要调优或扩容了日志方面docmost 容器 log 会滚动写长期运行建议配置一下 Docker 的 log rotation避免单个日志文件无限膨胀撑爆磁盘。6. 实际部署中遇到的问题和排查方法6.1 高频问题速查表我把这段时间遇到和听同行提过的问题整理成了一张表基本上覆盖了绝大多数 docmost 部署初期会碰到的坑现象可能原因解决办法页面能开但协作光标不同步Nginx 没代理 WebSocket确认proxy_set_header Upgrade和Connection upgrade已配置上传大文件失败或 413 报错Nginxclient_max_body_size过小设置 100m 或与应用上传限制对齐容器反复重启日志报数据库连接错误Postgres 初始化未完成或密码不匹配检查POSTGRES_PASSWORD是否一致看 postgres 日志确认就绪打开页面白屏或 JS 资源加载失败APP_URL 与访问域名不一致把.env中的 APP_URL 改成实际域名重启 docmost中文内容搜索命中不完整未对全文检索调优保证数据库连接串中 charset 正确索引重建可咨询官方文档SMTP 发送邀请邮件失败邮件服务地址或授权码错误检查发件邮箱是否开启 SMTP授权码是否有效排除 465/587 端口被防火墙挡系统内存持续走高并 OOM容器无限制共用宿主机资源在 compose 中设置mem_limit: 2g或升级机器配置页面弹出 503升级期间迁移未完成查看docker compose logs docmost等待迁移结束必要时检查 postgres 负载6.2 我踩过的一个典型的坑APP_URL 忘记改第一次测试时我在 .env 里用的是系统默认的APP_URLhttp://localhost:3000通过 Nginx 域名访问时页面能打开但页脚分享链接和 API 回调地址全部指向 localhost。有同事把文档链接分享到群里别人点开直接跳到他自己电脑的 3000 端口自然是一片 404。后来我把 APP_URL 改成实际域名并重建容器后问题才彻底消失。这个变量平时不起眼但一旦用域名访问就绕不开建议部署第一天就配好。6.3 多人团队落地的一些额外经验部署技术本身只是第一步真正要让团队把文档平台用起来还涉及几个容易忽略的配套动作建空间之前先定权限模型。按“公开知识库”“部门内部”“单项目私密”三种粒度管理避免出现谁都能看所有文档的情况首页建议放一个“新手指南”告诉团队怎么写文档、怎么查找内容、遇到问题找谁跟 LDAP/OIDC 集成之前先用邮箱账号邀请跑通流程再逐步引入统一认证避免第一天就搞挂全员登录定期把历史遗留的云盘文档批量导入迁移干净后才能真正淘汰旧工具7. 我最终选定的配置和几层深挖后的建议部署验证完成后我把这套部署固化成了内部文档和脚本也顺手记录了一份当前生产配置清单。这里把核心配置贴出来方便你按同样的参数做基准测试主机2 核 4G 内存 Ubuntu 22.04系统盘 40G镜像版本docmost/docmost:0.8.1 postgres:16-alpine redis:7-alpine反代环境Nginx 1.18 ACME 自动续期证书数据目录/opt/docmost挂载 data、pgdata、redisdata 三个子目录访问地址https://docs.example.comWebSocket 已启用容器资源限制docmost 2g、postgres 1g、redis 512m这套配置下团队 30 人规模同时在线读写文档、协作编辑、全文检索都保持秒开。如果人数再往上走比如一百人以上瓶颈大概率会在数据库连接数和 Redis 内存上到时候优先给 Postgres 和 Redis 升配再考虑给 docmost 前面加缓存层。最后分享一个我自己亲测好用的组合docmost 只做协作编辑和知识沉淀对外输出的正式文档和客户方案仍然导出为 PDF 归档。这样既有团队协作的便利性又保留了对外交付的正式感。很多人忽略的是自托管平台真正的成本不在部署那一下而在后续的备份纪律和升级习惯。只要把这套流程固定下来docmost 就能老老实实当团队的数字底座。
返回列表