Apache ManifoldCF 2.31 Docker Compose 部署指南
使用 Docker Compose 在单机一键部署 Apache ManifoldCF 2.31,自建 OpenJDK 25 基础镜像、持久化 HSQLDB 数据与日志、配置文件外置、up/down 数据留存验证与端口/凭据自检,全部命令与回显实测
Apache ManifoldCF 2.31 Docker Compose 部署指南
目标:在一台装有 Docker 与 Docker Compose 的主机上,以容器方式一键部署 Apache ManifoldCF 2.31,实现配置外置、HSQLDB 数据与日志持久化,并通过 down/up 循环验证数据留存。文内 Dockerfile、docker-compose.yml、构建与运行回显、登录与数据持久化验证均逐条实测。
一、环境信息
| 项目 | 值 |
|---|---|
| 宿主机 | Ubuntu 22.04(x86_64) |
| Docker Engine | 29.8.0 |
| Docker Compose | v5.5.1(docker compose 插件) |
| 基础镜像 | ubuntu:22.04 |
| Apache ManifoldCF | 2.31(官方 binary 发行版,444,303,809 字节) |
| JDK | openjdk-25-jdk-headless(镜像内 apt 安装) |
| 对外端口 | 8345(爬虫 UI / API) |
| 部署目录 | /opt/data/quzuo/mcf-compose |
💡 本篇为容器化部署教程,命令均在 Docker 容器内实测执行;如需在物理服务器直接安装,见《Ubuntu 22.04 安装 Apache ManifoldCF 2.31 指南》。
二、前置条件
安装 Docker 与 Compose 插件后确认版本:
docker info --format '{{.ServerVersion}}'
docker compose version
回显:
29.8.0
Docker Compose version v5.5.1
准备部署目录并下载发行包(推荐清华镜像;官方 dlcdn 直连实测仅约 100KB/s):
mkdir -p /opt/data/quzuo/mcf-compose/conf
cd /opt/data/quzuo/mcf-compose
wget -O apache-manifoldcf-2.31-bin.tar.gz \
https://mirrors.tuna.tsinghua.edu.cn/apache/manifoldcf/apache-manifoldcf-2.31/apache-manifoldcf-2.31-bin.tar.gz
下载校验文件并核对 sha512(清华镜像不提供 .sha512,实测 404;从 dlcdn 获取):
wget https://dlcdn.apache.org/manifoldcf/apache-manifoldcf-2.31/apache-manifoldcf-2.31-bin.tar.gz.sha512
cat apache-manifoldcf-2.31-bin.tar.gz.sha512
sha512sum apache-manifoldcf-2.31-bin.tar.gz
回显:
apache-manifoldcf-2.31-bin.tar.gz: 6975EA2C 5243E485 21B2259E 3B17297B 93B49CB1
EEAE0E87 24B3BAC6 1A2E1FEF E1038E47 5A3CDE19
0925E883 FBF5172D 327CB7E4 295C30B4 C542958F
ED260B28
6975ea2c5243e48521b2259e3b17297b93b49cb1eeae0e8724b3bac61a2e1fefe1038e475a3cde190925e883fbf5172d327cb7e4295c30b4c542958fed260b28 apache-manifoldcf-2.31-bin.tar.gz
校验一致后,目录最终结构:
/opt/data/quzuo/mcf-compose/
├── apache-manifoldcf-2.31-bin.tar.gz # 444303809 字节
├── Dockerfile
├── docker-compose.yml
├── conf/
│ └── properties.xml # 外置配置(挂载进容器)
├── data/ # HSQLDB 数据(运行时生成)
└── logs/ # 运行日志(运行时生成)
💡 Docker Hub 直连被拒的环境需先配置镜像加速(实测回显:
dial tcp 205.186.152.122:443: connect: connection refused)。在/etc/docker/daemon.json写入:
{"registry-mirrors":["https://docker.1ms.run","https://docker.m.daocloud.io"]}
然后重启 Docker 服务使配置生效。
三、准备镜像构建文件
3.1 Dockerfile
创建 /opt/data/quzuo/mcf-compose/Dockerfile:
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends openjdk-25-jdk-headless \
&& rm -rf /var/lib/apt/lists/*
COPY apache-manifoldcf-2.31-bin.tar.gz /opt/
RUN cd /opt \
&& tar xzf apache-manifoldcf-2.31-bin.tar.gz \
&& mv apache-manifoldcf-2.31 manifoldcf-2.31 \
&& rm -f apache-manifoldcf-2.31-bin.tar.gz \
&& find /opt/manifoldcf-2.31 -name "*.sh" -exec chmod +x {} \; \
&& mkdir -p /var/lib/manifoldcf
ENV JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
WORKDIR /opt/manifoldcf-2.31/example
EXPOSE 8345
CMD ["./start-combined.sh"]
要点:
- ManifoldCF 2.31 class 文件版本 69.0,必须安装 OpenJDK 25,Java 11 启动会报
UnsupportedClassVersionError。 find ... -exec chmod +x修复官方包内.sh无执行权限的问题(实测不加会Permission denied)。WORKDIR必须是example/:properties.xml、jetty.xml、启动脚本均按相对路径定位。start-combined.sh前台启动单个 JVM(UI + authority + API + agents 一体),默认堆 512MB,符合容器内存限制要求。
3.2 外置 properties.xml
创建 /opt/data/quzuo/mcf-compose/conf/properties.xml(在发行包 example/properties.xml 基础上做两处修改:HSQLDB 数据路径指向挂载目录、写入管理员凭据):
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- Version string for UI -->
<property name="org.apache.manifoldcf.versionstring" value="2.31"/>
<!-- Point to the wars and configure Jetty -->
<property name="org.apache.manifoldcf.crawleruiwarpath" value="../web/war/mcf-crawler-ui.war"/>
<property name="org.apache.manifoldcf.authorityservicewarpath" value="../web/war/mcf-authority-service.war"/>
<property name="org.apache.manifoldcf.apiservicewarpath" value="../web/war/mcf-api-service.war"/>
<property name="org.apache.manifoldcf.usejettyparentclassloader" value="true"/>
<property name="org.apache.manifoldcf.jettyconfigfile" value="./jetty.xml"/>
<!-- Point to the combined war in case we start the single-process example that way -->
<property name="org.apache.manifoldcf.combinedwarpath" value="../web/war/mcf-combined-service.war"/>
<!-- Select HSQLDB as the database implementation, and specify where the database will be stored -->
<property name="org.apache.manifoldcf.databaseimplementationclass" value="org.apache.manifoldcf.core.database.DBInterfaceHSQLDB"/>
<property name="org.apache.manifoldcf.hsqldbdatabasepath" value="/var/lib/manifoldcf"/>
<property name="org.apache.manifoldcf.database.maxhandles" value="100"/>
<property name="org.apache.manifoldcf.crawler.threads" value="50"/>
<property name="org.apache.manifoldcf.crawler.historycleanupinterval" value="2592000000"/>
<!-- Point to a specific logging file -->
<property name="org.apache.manifoldcf.logconfigfile" value="./logging.xml"/>
<!-- Specify the connectors to be loaded -->
<property name="org.apache.manifoldcf.connectorsconfigurationfile" value="../connectors.xml"/>
<!-- Specify the path to the file resources directory -->
<property name="org.apache.manifoldcf.fileresources" value="../file-resources"/>
<!-- Tell MCF where to find the connector jars -->
<libdir path="../connector-lib"/>
<libdir path="../connector-common-lib"/>
<libdir path="../connector-lib-proprietary"/>
<!-- Login credentials for crawler UI and API -->
<property name="org.apache.manifoldcf.login.name" value="admin"/>
<property name="org.apache.manifoldcf.login.password" value="q1w2e3r4"/>
<property name="org.apache.manifoldcf.apilogin.name" value="admin"/>
<property name="org.apache.manifoldcf.apilogin.password" value="q1w2e3r4"/>
<!-- Any additional properties go here -->
</configuration>
与原版相比的修改点:
| 修改 | 原值 | 新值 | 目的 |
|---|---|---|---|
org.apache.manifoldcf.hsqldbdatabasepath | . | /var/lib/manifoldcf | 数据落到挂载卷,容器重建不丢 |
org.apache.manifoldcf.login.name/password | admin/admin(默认) | admin/q1w2e3r4 | 修改默认 UI 凭据 |
org.apache.manifoldcf.apilogin.name/password | 空/空(默认) | admin/q1w2e3r4 | 修改默认 API 凭据 |
3.3 docker-compose.yml
创建 /opt/data/quzuo/mcf-compose/docker-compose.yml:
services:
manifoldcf:
build: .
image: manifoldcf-2.31:latest
container_name: manifoldcf-231
restart: unless-stopped
ports:
- "8345:8345"
environment:
JAVA_HOME: /usr/lib/jvm/java-25-openjdk-amd64
volumes:
- ./conf/properties.xml:/opt/manifoldcf-2.31/example/properties.xml
- ./data:/var/lib/manifoldcf
- ./logs:/opt/manifoldcf-2.31/example/logs
设计说明:
ports映射 8345,宿主机直接访问http://<宿主IP>:8345/mcf/。- 三条挂载:properties.xml 外置(改配置不用重建镜像)、HSQLDB 数据持久化到
./data、日志持久化到./logs。 restart: unless-stopped保证宿主机重启后服务自动拉起。
四、构建与启动
4.1 构建镜像
cd /opt/data/quzuo/mcf-compose
docker compose build
真实回显(尾部):
#11 unpacking to docker.io/library/manifoldcf-2.31:latest 24.5s done
#12 resolving provenance for metadata file
Image manifoldcf-2.31:latest Built
查看镜像:
docker images manifoldcf-2.31
回显:
IMAGE ID DISK USAGE CONTENT SIZE
manifoldcf-2.31:latest 6a989d54616d 2.49GB 1.1GB
4.2 启动服务
docker compose up -d
回显:
Container manifoldcf-231 Created
Container manifoldcf-231 Starting
Container manifoldcf-231 Started
4.3 状态与日志
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
docker compose logs manifoldcf | tail -3
回显:
NAME STATUS PORTS
manifoldcf-231 Up 45 seconds 0.0.0.0:8345->8345/tcp, [::]:8345->8345/tcp
Successfully registered notification connector 'org.apache.manifoldcf.crawler.notifications.rocketchat.RocketChatConnector'
Successfully registered notification connector 'org.apache.manifoldcf.crawler.notifications.email.EmailConnector'
Jetty started.
启动约需 30-40 秒(注册全部连接器),以日志出现 Jetty started. 为就绪标志。
五、验证
5.1 Web 入口与登录
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://localhost:8345/mcf/
回显:
302 -> http://localhost:8345/mcf/login.jsp
使用外置凭据登录(POST 到登录处理页 setupAdminProfile.jsp):
curl -s -c /tmp/cj -o /dev/null -w "login(q1w2e3r4): %{http_code} -> %{redirect_url}\n" \
-d "userID=admin&password=q1w2e3r4" http://localhost:8345/mcf/setupAdminProfile.jsp
curl -s -o /dev/null -w "login(admin): %{http_code} -> %{redirect_url}\n" \
-d "userID=admin&password=admin" http://localhost:8345/mcf/setupAdminProfile.jsp
回显:
login(q1w2e3r4): 302 -> http://localhost:8345/mcf/index.jsp
login(admin): 302 -> http://localhost:8345/mcf/login.jsp?loginfailed=true
新凭据登录成功跳转管理台;发行包默认的 admin/admin 被拒绝(进入镜像的 properties.xml 已被挂载替换生效)。
浏览器访问 http://<宿主IP>:8345/mcf/,输入 admin / q1w2e3r4 进入爬虫管理界面。
5.2 持久化目录检查
宿主机查看挂载产物:
ls data/
ls logs/
回显:
dbname.data dbname.lck dbname.log dbname.properties dbname.script dbname.tmp
manifoldcf.log
HSQLDB 数据文件与运行日志均已落在宿主目录。
5.3 数据留存端到端验证(down → up)
先通过 API 创建一个输出连接作为"存量数据":
D=http://localhost:8345/mcf/api
curl -s -c /tmp/ac -X POST -H "Content-Type: application/json" \
-d '{"userID":"admin","password":"q1w2e3r4"}' $D/json/LOGIN
echo
curl -s -b /tmp/ac -X PUT -H "Content-Type: application/json" \
-d '{"outputconnection":{"description":"Persistence test","configuration":{},"class_name":"org.apache.manifoldcf.agents.output.filesystem.FileOutputConnector","name":"PersistedOutput","max_connections":"100"}}' \
$D/json/outputconnections/PersistedOutput
echo
curl -s -b /tmp/ac $D/json/outputconnections | head -c 200
回显:
{}
{}
{"outputconnection":{"_children_":[{"_type_":"isnew","_value_":"false"},{"_type_":"name","_value_":"PersistedOutput"},{"_type_":"class_name","_value_":"org.apache.manifoldcf.agents.output.filesystem.FileOutputConnector"},{"_type_":"max_connections","_value_":"100"},{"_type_":"description","_value_":"Persistence test"},{"_type_":"configuration"}]}}
销毁并重建容器:
docker compose down
回显:
Network mcf-compose_default Removing
Network mcf-compose_default Removed
确认数据目录未受影响:
ls data/
回显:
dbname.data
dbname.lck
dbname.log
dbname.properties
dbname.script
dbname.tmp
再次启动:
docker compose up -d
回显:
Container manifoldcf-231 Starting
Container manifoldcf-231 Started
等待约 40 秒后重新登录并查询:
D=http://localhost:8345/mcf/api
curl -s -c /tmp/ad -X POST -H "Content-Type: application/json" \
-d '{"userID":"admin","password":"q1w2e3r4"}' $D/json/LOGIN
curl -s -b /tmp/ad $D/json/outputconnections | head -c 300
回显:
{}
{"outputconnection":{"_children_":[{"_type_":"isnew","_value_":"false"},{"_type_":"name","_value_":"PersistedOutput"},{"_type_":"class_name","_value_":"org.apache.manifoldcf.agents.output.filesystem.FileOutputConnector"},{"_type_":"max_connections","_value_":"100"},{"_type_":"description","_value_":"Persistence test"},
PersistedOutput 在容器销毁重建后依然存在(isnew=false),持久化验证通过。容器状态:
docker compose ps --format "{{.Name}} {{.Status}}"
回显:
manifoldcf-231 Up 42 seconds
六、运行维护
- 启动/停止/重启:
docker compose start | stop | restart;配置文件(properties.xml)修改后执行docker compose restart生效。 - 日志:
docker compose logs -f manifoldcf跟踪标准输出;落盘日志在./logs/manifoldcf.log。 - 进入容器排查:
docker compose exec manifoldcf bash。 - 数据备份:直接备份宿主机
./data/目录(HSQLDB 文件),建议先docker compose stop再打包。 - 升级:替换构建上下文中的发行包(如
apache-manifoldcf-2.32-bin.tar.gz)、修改 Dockerfile 与 properties.xml 中版本相关字段后docker compose build && docker compose up -d,数据因挂载保留。 - 内存:combined 默认堆 512MB(Dockerfile 内 options 文件未改动),可进入容器修改
example/combined-options.env.unix后重启生效。
七、常见问题(FAQ)
Q1:docker compose build 报拉取镜像失败?
现象(实测):
failed to resolve source metadata for docker.io/library/ubuntu:22.04:
dial tcp 205.186.152.122:443: connect: connection refused
解决:在 /etc/docker/daemon.json 配置 registry-mirrors(见第二章)并重启 Docker 后重试。
Q2:容器反复重启,日志报 UnsupportedClassVersionError?
基础镜像 JDK 版本低于 25 所致。确保 Dockerfile 使用 openjdk-25-jdk-headless(ManifoldCF 2.31 class 文件版本 69.0),重新 docker compose build。
Q3:start-combined.sh: Permission denied 且容器退出?
官方包内 .sh 无执行位。确认 Dockerfile 中包含:
RUN find /opt/manifoldcf-2.31 -name "*.sh" -exec chmod +x {} \;
Q4:数据没有持久化,down 后配置的连接丢失?
检查 docker-compose.yml 挂载是否齐全:./data:/var/lib/manifoldcf 与外置 conf/properties.xml(其中 hsqldbdatabasepath 必须指向 /var/lib/manifoldcf)。两处任一缺失都会导致数据落在容器可写层而被销毁。
Q5:访问 8345 端口 404?
combined 模式入口是 http://<IP>:8345/mcf/(不是 /mcf-crawler-ui/)。实测:
# curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8345/mcf-crawler-ui/
404
# curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8345/mcf/
302
Q6:启动后立即访问 503/连接被拒?
连接器注册需 30-40 秒,以 docker compose logs 出现 Jetty started. 为准再访问。
八、卸载与清理
cd /opt/data/quzuo/mcf-compose
docker compose down --rmi local
回显(尾部):
Container manifoldcf-231 Stopping
Container manifoldcf-231 Stopped
Container manifoldcf-231 Removing
Container manifoldcf-231 Removed
如确认不再需要数据,删除数据目录与构建上下文:
rm -rf /opt/data/quzuo/mcf-compose/data /opt/data/quzuo/mcf-compose/logs
九、参考链接
- 官方下载(含校验与签名):https://dlcdn.apache.org/manifoldcf/apache-manifoldcf-2.31/
- 2.31 最终用户文档:https://manifoldcf.apache.org/release/release-2.31/en_US/end-user-documentation.html
- 2.31 编程接口文档:https://manifoldcf.apache.org/release/release-2.31/en_US/programmatic-operation.html
- Dockerfile / Compose 官方参考:https://docs.docker.com/reference/dockerfile/ ,https://docs.docker.com/compose/
- 项目主页:https://manifoldcf.apache.org/