XWiki 18.8 Docker Compose 部署指南

用 Docker Compose 在 Linux 服务器部署 XWiki 18.8.0(官方镜像 + PostgreSQL 16):网络与目录规划、首次启动向导、数据持久化与备份实测、环境变量与配置挂载机制、等价 docker run、healthcheck 与运维排障实录。

XWikiXWikiWiki知识库2026/10/22

XWiki 18.8 Docker Compose 部署指南

目标:在一台 Linux 服务器上用 Docker Compose 部署 XWiki 18.8.0(官方镜像 xwiki:18.8.0-postgres-tomcat + PostgreSQL 16),完成网络与目录规划、首次启动 Distribution Wizard 初始化、数据持久化与备份验证、healthcheck 配置,并沉淀部署过程中的真实排障记录。本文所有命令与回显均在下述环境逐条实测。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(PRETTY_NAME 实测回显)
  • 容器运行时:Docker 29.8.1(API 1.56),Docker Compose v5.5.1(docker compose version 实测)
  • 硬件:12 vCPU / 31 GiB 内存 / 786 GB 数据盘(已用 50%)
  • XWiki 镜像:xwiki:18.8.0-postgres-tomcat(Docker Official Image)
    • 镜像大小:2.53 GB,镜像 ID 13ee48698a65
    • 摘要:xwiki@sha256:13ee48698a658362f32d061c4777b2686dc961eb6f82de52e9f724fa33b8efec(docker inspect 实测)
    • 内含组件(容器内实测):OpenJDK 21.0.12.1 LTS、Apache Tomcat 10.1.61
  • 数据库镜像:postgres:16(容器内实测 server_version 为 16.15)
  • 网络规划:专用桥接网络 xwiki-18.8.0-net,网段 10.89.79.0/24
  • 端口规划:宿主机 8148 → 容器 8080
  • 目录规划:配置与运行产物统一放在 /opt/data/xwiki/(部署目录 compose/、XWiki 永久目录 xwiki-data/、数据库目录 db-data/)
  • 版本选择依据:18.8.0 为官方最新稳定版(GitHub Release 发布于 2026-09-29),版本线全景见 《XWiki 介绍与选型指南》

二、镜像选型说明

2.1 为什么是 xwiki:18.8.0-postgres-tomcat

XWiki 官方在 Docker Hub 维护的是官方镜像(Docker Official Image)xwiki,tag 命名规则为 <版本>-<数据库>-<Web容器>:

tag数据库说明
18.8.0-postgres-tomcatPostgreSQL本文实测使用;生产推荐
18.8.0-mysql-tomcatMySQL 8生产可选
18.8.0-mariadb-tomcatMariaDB生产可选
stable / lts随构建漂移漂移 tag,指向会变,生产不建议直接使用

💡 说明:XWiki 内置的 HSQLDB 文件库仅适合一次性评估,容器版镜像全部打包的是生产级数据库驱动组合。数据库选型对比见 《XWiki 介绍与选型指南》 第七章。

⚠️ 注意:实测当日 stable 漂移 tag 的镜像摘要与 18.8.0-postgres-tomcat 一致(digest 前 14 位均为 sha256:13ee48698a658),但漂移 tag 在上游发布新版本后会静默变化。生产环境建议固定完整版本号 tag,或直接固定摘要。

2.2 固定摘要的拉取方式(可选加固)

docker pull xwiki@sha256:13ee48698a658362f32d061c4777b2686dc961eb6f82de52e9f724fa33b8efec

本文使用版本号 tag xwiki:18.8.0-postgres-tomcat 拉取,docker images 实测回显:

xwiki        18.8.0-postgres-tomcat   13ee48698a65   2.53GB

三、前置条件

  1. 已安装 Docker Engine 与 compose 插件(本文实测版本见第一章)。
  2. 宿主机 8148 端口空闲(可在防火墙放行该端口供局域网访问)。
  3. 磁盘预留:镜像 2.53 GB;XWiki 永久目录(含 Solr 索引、扩展缓存、日志)与 PostgreSQL 数据目录建议各预留 10 GB 起步。
  4. 创建专用网络并规划目录:
docker network create --subnet=10.89.79.0/24 xwiki-18.8.0-net
mkdir -p /opt/data/xwiki/compose /opt/data/xwiki/xwiki-data /opt/data/xwiki/db-data

创建结果用 docker network ls 验证(实测回显):

NETWORK ID     NAME               DRIVER    SCOPE
07f260da4d80   xwiki-18.8.0-net   bridge    local

四、部署步骤

4.1 编排文件 docker-compose.yml

写入 /opt/data/xwiki/compose/docker-compose.yml(本文实测文件全文):

name: xwiki-18.8.0-stack

services:
  db:
    image: postgres:16
    container_name: xwiki-18.8.0-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=xwiki
      - POSTGRES_PASSWORD=xwiki
      - POSTGRES_DB=xwiki
    volumes:
      - /opt/data/xwiki/db-data:/var/lib/postgresql/data
    networks:
      - xwiki-net

  web:
    image: xwiki:18.8.0-postgres-tomcat
    container_name: xwiki-18.8.0-web
    restart: unless-stopped
    depends_on:
      - db
    ports:
      - "8148:8080"
    environment:
      - DB_HOST=db
      - DB_DATABASE=xwiki
      - DB_USER=xwiki
      - DB_PASSWORD=xwiki
      - JAVA_OPTS=-Xms512m -Xmx1024m
    volumes:
      - /opt/data/xwiki/xwiki-data:/usr/local/xwiki/data
    healthcheck:
      test: ["CMD-SHELL", "code=$$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/) && { [ \"$$code\" = \"302\" ] || [ \"$$code\" = \"200\" ]; }"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 120s
    networks:
      - xwiki-net

networks:
  xwiki-net:
    external: true
    name: xwiki-18.8.0-net

💡 技术拓展:healthcheck.test 里探测的是容器根路径 /。XWiki 对未登录请求返回 302(跳转登录页/初始化向导),登录后访问 /bin/view/Main/ 返回 200,因此健康判定同时接受 302 与 200。不要用 /bin/login/XWiki/XWikiLogin 做健康探测——实测该路径匿名访问返回 401(见第十一章 FAQ)。

4.2 启动

cd /opt/data/xwiki/compose
docker compose up -d

启动输出(节选,实测):

 Container xwiki-18.8.0-db Starting
 Container xwiki-18.8.0-db Started
 Container xwiki-18.8.0-web Starting
 Container xwiki-18.8.0-web Started

首次启动 XWiki 需要初始化数据库模式并启动内嵌 Solr。容器标准输出中 Tomcat 完成启动的标志行(docker logs xwiki-18.8.0-web 实测):

INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [12231] milliseconds

同时 XWiki 自身日志写入永久目录 /opt/data/xwiki/xwiki-data/logs/xwiki.log(实测首行加载 xwiki.properties、声明永久目录):

INFO iPropertiesConfigurationSource - Loading [xwiki.properties] from [file:/usr/local/tomcat/webapps/ROOT/WEB-INF/xwiki.properties]
INFO o.x.e.i.ServletEnvironment     - Using permanent directory [/usr/local/xwiki/data]

4.3 首次初始化:Distribution Wizard

首次用浏览器访问 http://<服务器IP>:8148/ 会进入 Distribution Wizard(发行版向导)。向导按 5 步推进(页面实测解析):

步骤名称要做的事
1Welcome欢迎页,直接继续
2Admin user创建管理员账号,表单字段实测为 xwikiname(用户名)、register_password、register2_password(两次口令)、register_email;本文创建 admin / q1w2e3r4
3Flavor安装标准 flavor(org.xwiki.platform:xwiki-platform-distribution-flavor-common:18.8.0)。实测该步骤在后台跑 install 任务(任务标识 install/flavor-setup),依赖解析日志 2400+ 条,从开始到 FINISHED 约 5 分钟,期间勿中断容器
4Orphaned dependencies / Extensions扩展与孤立依赖检查
5Report汇报页,点击完成按钮(表单按钮值实测为 COMPLETE_STEP)结束向导

向导每一步的表单都带 action 按钮,取值实测为 COMPLETE_STEP / SKIP_STEP / CANCEL_STEP。用 curl 驱动时提交 action=COMPLETE_STEP 即推进(实测回显:提交后最终 302 回 /bin/view/Main/,页面标题 Home)。

⚠️ 注意:向导状态会持久化。如果中途直接去访问普通页面,会被 302 重定向回 /bin/distribution/XWiki/Distribution,直到向导走完(排障实录见第十一章)。

4.4 部署验证

向导完成后逐项验证(实测命令与回显):

# 1. Web 首页
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8148/bin/view/Main/
# 实测:200

# 2. REST 接口探测(XWiki 以 ROOT 上下文部署,REST 前缀是 /rest 而非 /xwiki/rest)
curl -s -o /dev/null -w '%{http_code}\n' \
  -u admin:q1w2e3r4 \
  "http://localhost:8148/rest/wikis/xwiki/spaces/Main/pages/WebHome"
# 实测:200,页面标题 <title>Home</title>

# 3. 写权限验证(匿名 PUT 返回 401,认证后 PUT 返回 201/202)
# 4. 数据库侧确认
docker exec xwiki-18.8.0-db psql -U xwiki -d xwiki -t -c "SELECT count(*) FROM xwikidoc;"

REST 前缀这一点容易踩坑:该镜像把 XWiki 部署在 Tomcat 的 ROOT 上下文(entrypoint 默认 CONTEXT_PATH=ROOT),所以 REST API 的路径是 /rest/...;访问 /xwiki/rest/... 会被当成名为 xwiki 的子 wiki 页面处理而返回 404(实测)。

五、数据持久化说明

5.1 两个数据落点

挂载宿主目录容器路径存放内容
XWiki 永久目录/opt/data/xwiki/xwiki-data/usr/local/xwiki/data配置覆盖文件(xwiki.cfg 等)、日志 logs/、内嵌 Solr 索引 store/solr/、扩展缓存 extension/、任务状态 jobs/、临时目录 tmp/(每次启动清空重建)
PostgreSQL 数据/opt/data/xwiki/db-data/var/lib/postgresql/data全部页面/用户/对象/附件数据(实测库内 41 张含数据表,xwikidoc 为主文档表)

💡 说明:页面正文、用户、权限、附件默认都存 PostgreSQL;永久目录里的 Solr 是可重建的搜索索引。所以备份的重点是数据库(见 5.3),永久目录备份属于加速恢复的可选项。

5.2 停启与持久化实测

cd /opt/data/xwiki/compose
docker compose down          # 实测耗时 real 0m2.072s
docker compose up -d

重启后等待就绪的探测循环(探测 http://localhost:8148/bin/view/Main/ 返回 200 为准):实测 26 秒就绪。重启前后各查一次文档总数,均为 1519,实验创建的页面 REST 访问依旧 200,admin 账号照常登录——数据完整保留。

5.3 数据库备份与校验

# 导出(容器内执行 pg_dump 自定义格式归档)
docker exec xwiki-18.8.0-db pg_dump -U xwiki -d xwiki -Fc -f /tmp/xwiki-backup.dump
# 拷出到宿主机
docker cp xwiki-18.8.0-db:/tmp/xwiki-backup.dump /opt/data/xwiki/xwiki-backup.dump
ls -lh /opt/data/xwiki/xwiki-backup.dump

实测回显:

-rw-r--r-- 1 root root 3.5M 10月 22 07:24 xwiki-backup.dump

归档合法性校验(列出归档内含数据的表数量):

docker exec xwiki-18.8.0-db pg_restore --list /tmp/xwiki-backup.dump | grep -cE 'TABLE DATA'
# 实测:41

六、环境变量表

以下变量由镜像内置的启动脚本 docker-entrypoint.sh 消费(实读容器内 /usr/local/bin/docker-entrypoint.sh 确认),全部支持 <变量名>_FILE 形式从文件读取值(适配 Docker secrets;<VAR> 与 <VAR>_FILE 同时设置会直接报错退出):

变量默认值作用
DB_USERxwiki数据库用户名,注入 hibernate.cfg.xml
DB_PASSWORDxwiki数据库口令,注入 hibernate.cfg.xml
DB_HOSTdb数据库主机名(compose 服务名)
DB_PORT空数据库端口;留空用驱动默认(5432),设置后以 DB_HOST:DB_PORT 拼入 JDBC URL
DB_DATABASExwiki数据库名
SOLR_BASE_URL空留空使用内嵌 Solr;设置后写入 solr.type=remote 与 solr.remote.baseURL 接远程 Solr 集群
JDBC_PARAMS?JDBC 附加参数(自带 ? 前缀,如 ?useSSL=false)
CONTEXT_PATHROOTWeb 上下文路径;非 ROOT 时会把 webapp 复制到对应目录并移除 ROOT
JAVA_OPTS镜像内置JVM 参数,常用于堆内存设置

数据库服务侧(postgres:16 官方镜像):

变量本文取值作用
POSTGRES_USERxwiki初始超级用户(须与 web 的 DB_USER 一致)
POSTGRES_PASSWORDxwiki初始口令(须与 DB_PASSWORD 一致)
POSTGRES_DBxwiki初始数据库(须与 DB_DATABASE 一致)

entrypoint 首次启动还会固定写入两个配置项(脚本实读确认):environment.permanentDirectory=/usr/local/xwiki/data(永久目录指向挂载卷)与 openoffice.autoStart=true(Office 服务端渲染自启)。JAVA_OPTS 设置后可在容器内用 ps 验证,实测回显(节选):

/opt/java/openjdk/bin/java ... -Xms512m -Xmx1024m ... -Djava.io.tmpdir=/usr/local/xwiki/data/tmp org.apache.catalina.startup.Bootstrap start

💡 说明:-Djava.io.tmpdir 指向永久卷的 tmp/ 子目录,且启动脚本每次启动都会清空重建该目录——这是官方为避免临时文件写满小容量 tmpfs 做的设计(脚本注释引用 XDOCKER-321)。

七、配置参数说明

容器版 XWiki 的配置体系由三个文件构成,全部位于容器内 /usr/local/tomcat/webapps/ROOT/WEB-INF/:

文件职责
xwiki.cfgXWiki 核心配置:认证方式、超级管理员应急口令、wiki 描述等
xwiki.properties平台级配置:永久目录、Solr、扩展仓库、观测项等
hibernate.cfg.xml数据库连接:JDBC URL、用户名、口令、连接池(由 entrypoint 用 DB_* 变量 sed 注入)

DB_* 环境变量的本质就是首启时对 hibernate.cfg.xml 做 sed 替换(脚本中依次替换 user、password、host:port、database、jdbc params 五处),改动环境变量后重建容器(docker compose up -d)才会生效。

逐参数解析与生产配置模板见 《XWiki 18.8 配置参数详解》。

八、配置文件挂载:正确姿势与反面实录

8.1 官方覆盖机制

镜像约定:把配置文件放进永久目录(挂载卷 /usr/local/xwiki/data),启动脚本会自动同步进 WEB-INF:

  • 首次启动(configure()):若 data/xwiki.cfg、data/xwiki.properties、data/hibernate.cfg.xml 存在,则复制进 WEB-INF(日志输出 Reusing existing config file ...);
  • 后续启动(other_starts()):每次启动都把这三个文件从 data/ 同步进 WEB-INF(日志输出 Synchronizing config file ...)。

因此配置变更的正确流程是:docker cp 把容器内当前配置拷出到永久目录 → 修改 → 重启容器。

8.2 反面实录:直接改容器内 WEB-INF 会随重建丢失

实测过程(真实排障记录):

  1. 为启用超级管理员应急账号,直接在运行中的容器内修改了 WEB-INF/xwiki.cfg(启用 xwiki.superadminpassword),重启后验证通过;
  2. 执行 docker compose down && docker compose up -d 后,该修改随容器重建丢失(容器文件层不持久),以该账号调 REST 写接口实测返回 401;
  3. 同时启动日志里也没有 Synchronizing config file 行——因为永久目录里没有覆盖文件。

8.3 正确做法实测

# 1. 把容器内当前生效的 xwiki.cfg 拷出到永久目录
docker cp xwiki-18.8.0-web:/usr/local/tomcat/webapps/ROOT/WEB-INF/xwiki.cfg \
  /opt/data/xwiki/xwiki-data/xwiki.cfg

# 2. 修改(本例启用超级管理员应急口令,模板行 304)
sed -i 's/^# xwiki.superadminpassword=system$/xwiki.superadminpassword=q1w2e3r4/' \
  /opt/data/xwiki/xwiki-data/xwiki.cfg
grep -n 'superadminpassword' /opt/data/xwiki/xwiki-data/xwiki.cfg

实测回显:

304:xwiki.superadminpassword=q1w2e3r4
# 3. 重启容器并观察同步日志
docker restart xwiki-18.8.0-web
docker logs xwiki-18.8.0-web --since 1m 2>&1 | grep -E 'Configuring|Synchronizing|Server startup'

实测回显:

  Synchronizing config file xwiki.cfg...
INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [12020] milliseconds

验证:以 superadmin 账号对 REST 执行 PUT,实测返回 202(此前为 401);随后再执行一次 docker compose up -d 完整重建容器,该配置依旧生效(再次 PUT 返回 202)——证明经永久目录下发的配置在重建后依然保留。

⚠️ 注意:xwiki.superadminpassword 是官方提供的应急恢复口令(xwiki.cfg 模板注释原文:for recovering the Wiki when the rights are completely messed),仅建议临时启用排障;自 18.8.0 RC1 起支持哈希格式 {hashAlgorithm}hash(可用 htpasswd -bnBC 10 "" yourpassword | tr -d ':\n' 生成),避免明文落盘。

九、等价 docker run 启动方式

不使用 compose 时,两条 docker run 可等价启动同一套栈(以下命令与回显均为实测;在已建好的 xwiki-18.8.0-net 网络上演示,端口换用 8149 避免与本栈冲突):

# 1. 数据库
docker run -d --name xwiki-cli-db --network xwiki-18.8.0-net --network-alias db-cli \
  -e POSTGRES_USER=xwiki -e POSTGRES_PASSWORD=xwiki -e POSTGRES_DB=xwiki \
  -v /opt/data/xwiki/db-data-cli:/var/lib/postgresql/data \
  postgres:16

# 2. XWiki
docker run -d --name xwiki-cli-web --network xwiki-18.8.0-net \
  -p 8149:8080 \
  -e DB_HOST=db-cli -e DB_DATABASE=xwiki -e DB_USER=xwiki -e DB_PASSWORD=xwiki \
  -e 'JAVA_OPTS=-Xms512m -Xmx1024m' \
  -v /opt/data/xwiki/xwiki-data-cli:/usr/local/xwiki/data \
  xwiki:18.8.0-postgres-tomcat

实测要点:

  • 全新数据库的首次启动,Tomcat 启动完成标志(docker logs xwiki-cli-web 实测):Server startup in [11429] milliseconds;
  • 根路径探测 curl -s -o /dev/null -w '%{http_code}' http://localhost:8149/ 返回 302(未初始化时跳转向导)即为服务就绪;
  • 重启该容器后实测 13 秒即可响应;
  • 演示结束清理:docker rm -f xwiki-cli-web xwiki-cli-db 并删除两个演示数据目录。

⚠️ 注意:生产建议使用 compose。docker run 版本没有 healthcheck、restart 策略要手工携带、参数散落难审计,与第八章的配置同步机制配合时也更容易漏挂载。

十、常用运维命令

10.1 日常操作

cd /opt/data/xwiki/compose
docker compose ps                      # 栈内容器状态(含 health 列)
docker compose logs -f --tail=100 web  # 跟踪 web 日志
docker compose restart web             # 重启 web(数据不受影响)
docker compose down                    # 停止并移除容器(数据卷/绑定目录保留)
docker compose up -d                   # 启动/应用变更
docker compose pull                    # 检查并拉取镜像更新

docker compose pull 实测回显(固定版本 tag 时通常无更新):

 Image xwiki:18.8.0-postgres-tomcat Pulled
 Image postgres:16 Pulled

10.2 备份

按 5.3 节实测流程执行 pg_dump 归档导出即可;建议每日定时任务落盘到独立备份目录并异地留存。

10.3 升级流程

XWiki 的版本升级由「换镜像 tag + 启动后的 Distribution Wizard」共同完成:

# 1. 先做数据库备份(见 10.2)
# 2. 修改 docker-compose.yml 中 web 服务的 image tag(如 18.8.0 → 更新的稳定版本)
sed -i 's|xwiki:18.8.0-postgres-tomcat|xwiki:<新版本>-postgres-tomcat|' docker-compose.yml
# 3. 拉取新镜像并重建
docker compose pull && docker compose up -d
# 4. 浏览器访问站点,按 Distribution Wizard 提示完成升级确认与扩展升级

💡 说明:向导机制与 4.3 节首装向导同源(同样的步骤推进与 action 表单),升级时会额外出现「Update the installed extensions」类步骤(实测页面中出现该文案)。截至本文实测日 18.8.0 已是官方最新稳定版,故本文未执行跨版本升级的端到端实测;升级前务必先完成数据库备份,回滚即把 tag 改回旧版本重建(数据库请配合升级前的备份恢复)。

10.4 日志位置

日志位置
Tomcat/容器标准输出docker logs xwiki-18.8.0-web(Server startup in [...] 行即启动完成标志)
XWiki 应用日志宿主机 /opt/data/xwiki/xwiki-data/logs/xwiki.log(含遥测 WARN 等运行期记录)
PostgreSQL 日志docker logs xwiki-18.8.0-db

十一、常见问题(排障实录)

以下均为本文实测过程中真实发生并复现的问题。

11.1 访问首页被 302 到 /bin/distribution/XWiki/Distribution

现象:登录后访问 /bin/view/Main/ 返回 302,跳向 Distribution Wizard。 原因:向导状态未完结(XWiki 会持久化向导进度,重启或未走完 Report 步骤都会再次拦截)。 实测解法:向导页提交 action=COMPLETE_STEP(浏览器里点完最后一步即可),随后访问首页实测 200,页面标题 Home。

11.2 REST PUT 创建页面返回 Tomcat 400

现象:curl -X PUT 提交以 <?xml version="1.0" encoding="UTF-8" standalone="yes"?><page ...> 开头的 XML,返回 400。 原因:XML 声明头与根元素写在同一行不符合声明语法,Tomcat 直接拒绝。 实测解法:声明头之后必须换行再写根元素;改后同一请求返回 201(创建成功)。完整 REST 用法见 《XWiki 18.8 常用 REST API 与运维命令详解》。

11.3 日志持续出现 Active Installs 遥测 WARN

现象:xwiki.log 周期性出现:

WARN a.i.ActiveInstallsPingRunnable - Failed to send Active Installation ping to [https://extensions.xwiki.org/activeinstalls2] ... status: 403 ... Will retry in [1 days]...

原因与结论:这是 XWiki 向官方遥测端点上报安装统计的功能,网络出口拦截或端点拒绝时即产生该 WARN,重试 3 次后按天退避。不影响任何功能,仅是日志噪音;对安全敏感的部署可在外围限制容器对 extensions.xwiki.org 的出网访问,功能不受影响(本文全程在受限网络下实测)。

11.4 compose 项目名中的点号被剔除

现象:docker-compose.yml 写 name: xwiki-18.8.0-stack,但 docker compose config 解析结果为 name: xwiki-1880-stack(实测)。 原因:compose 项目名只允许小写字母、数字、连字符与下划线,点号被静默剔除。 建议:name 直接使用不含点号的写法(如 xwiki-18-8-0-stack),避免脚本按 name 引用项目时对不上;容器名已用 container_name 显式固定,不受影响。

11.5 用 /bin/login/... 做健康探测返回 401

现象:curl http://localhost:8148/bin/login/XWiki/XWikiLogin 匿名访问返回 401 而非 200。 结论:该路径对匿名请求直接 401,不适合做存活探测;健康检查请探测 /(未登录 302 / 正常 200,见 4.1 节 healthcheck)。

11.6 首次启动 Flavor 安装阶段耗时数分钟

现象:向导第 3 步页面停留较久。 实测数据:install 任务 install/flavor-setup 产生 2400+ 条依赖解析 INFO 日志,从启动到 FINISHED 约 5 分钟。 建议:属正常现象,等待即可;期间重启容器会中断安装,需清理任务状态后重来。

11.7 容器内直接修改配置在重建后丢失

现象与解法:完整实录见第八章——务必走「永久目录覆盖文件」机制,不要直接编辑容器内 WEB-INF。

十二、参考链接