DSpace 10.1 Docker Compose 部署指南
DSpace 10.1 Docker Compose 部署指南:基于 2026-11-01 在跑栈实录,五服务编排(REST 后端/Angular SSR 前端/Solr 七 core/PostgreSQL 15/nginx 统一入口 8139)、database migrate 与 create-administrator 初始化全流程、JVM 堆 256–512MB 治理与 jps 验证、六则排障实录,版本线交叉复核官方最新稳定版 10.1。
DSpace 10.1 Docker Compose 部署指南
目标:在一台 Linux 服务器上,用官方发布件(
dspace/dspace、dspace/dspace-angular、dspace/dspace-solr的dspace-10.1系标签)加 PostgreSQL 15 与 nginx,编排一套完整机构知识库栈,以 8139 端口为唯一对外入口。本文全部命令与回显均为 2026-11-01 部署实录;产品定位与选型对比见《DSpace 介绍与选型指南》,配置三层优先级链与关键项详解见《DSpace 配置参数详解(env/local.cfg/dspace.cfg 三层优先级链与关键项)》,REST API 逐条实测见《DSpace REST API 使用详解(HAL 超媒体认证、CRUD 与检索实测)》。
一、环境信息
| 项目 | 内容 |
|---|---|
| 实测日期 | 2026-11-01 |
| 编排工具 | Docker Compose v5.6.1(docker compose version 实测回显 "Docker Compose version v5.6.1") |
| 主机入口 | http://192.168.1.200:8139 (唯一对外端口) |
| REST 后端 | docker.io/dspace/dspace:dspace-10.1(Spring Boot 可运行 JAR server-boot.jar,内部 8080;Handle 服务内部 8000) |
| 前端 | docker.io/dspace/dspace-angular:dspace-10.1-dist(Angular SSR 生产构建,内部 4000,pm2-runtime 托管) |
| 检索 | docker.io/dspace/dspace-solr:dspace-10.1(内部 8983) |
| 数据库 | docker.io/postgres:15(内部 5432) |
| 反向代理 | docker.io/nginx:1.27-alpine(宿主 8139 → 内部 80) |
| 专用网络 | dspace-101-stack_dspacenet,子网 10.89.58.0/24(docker network inspect 实测) |
| 持久卷 | 命名卷 assetstore(资产目录)/ pgdata(数据库)/ solr_data(索引) |
| JDK 口径 | 后端 JDK 21(官方构建基线,Hibernate Validator 8.0.5.Final、Spring Boot v3.5.16 实测见第六节) |
| 示例管理员账号 | admin@dspace.local / q1w2e3r4(第六节 create-administrator 实录创建) |
二、版本线核对:10.1 即官方最新稳定版
部署前先核对版本线,结论(取证日期 2026-11-01):
- GitHub Releases 实查:DSpace/DSpace 仓库 Releases 页中,标签
dspace-10.1带官方 Latest 徽章,发布标题 "Release DSpace 10.1 (Backend / REST API Only)"(2026-09-14);同批还有维护线 9.4、8.5 更新,上一批(2026-05-28)为 10.0/9.3/8.4/7.6.7。即本例部署的 10.1 与官方最新稳定版一致。 - 前端版本对齐:Angular UI 在 dspace-angular 仓库独立发布,官方镜像提供与后端版本号对齐的
dspace-10.1-dist标签(Docker Hub 实查存在),本例直接采用。 - 官方警告如实记录(README 原文):"THESE IMAGES ARE NOT PRODUCTION READY"——官方发布件定位开发/测试。本文是官方发布件形态的完整可复现实录;若要生产使用,至少完成:改数据库口令与管理员口令、入口层启用 HTTPS、按第九节落实持久卷备份、按本专栏配置篇收紧
authentication-password.cfg等安全项。
💡 技术拓展:DSpace 后端与 UI 分仓分版本发布,10.1 后端标题即注明 "REST API Only";升级时两者要分别核对兼容矩阵,不能只盯后端版本号。
三、架构与组件规划
浏览器 ──▶ http://192.168.1.200:8139
│
nginx(dspace-proxy,内部 :80)
├── /server/ ──▶ dspace:8080 (REST 后端,/server 命名空间)
└── / ──▶ dspace-angular:4000 (Angular SSR 前端)
│
dspace ──▶ dspacedb:5432 (PostgreSQL 15,64 张表)
dspace ──▶ dspacesolr:8983 (Solr,7 个 core)
dspace ──▶ /dspace/assetstore (命名卷 assetstore)
要点:
- 五个服务同处专用网络 10.89.58.0/24,只有 proxy 映射宿主端口,后端/前端/数据库/检索均不对宿主直接暴露;
- Solr 的 7 个 core(实测目录清单):
audit、authority、oai、qaevent、search、statistics、suggestion,分别承担审计、规范引用、OAI-PMH 视图、质量事件、全站检索、使用统计、外部推荐; - 后端经反向代理访问,需显式信任代理网段(
proxies.trusted.ipranges),否则 X-Forwarded-For 不生效、统计 IP 全部记成代理地址。
四、compose 文件全文解读
以下为在跑栈的完整编排文件(docker-compose.yml,逐行照抄):
name: dspace-10.1-stack
networks:
dspacenet:
ipam:
config:
- subnet: 10.89.58.0/24
volumes:
assetstore:
pgdata:
solr_data:
services:
# DSpace PostgreSQL database
dspacedb:
container_name: dspace-10.1-db
image: docker.io/postgres:15
environment:
PGDATA: /pgdata
POSTGRES_DB: dspace
POSTGRES_USER: dspace
POSTGRES_PASSWORD: dspace
networks:
- dspacenet
volumes:
- pgdata:/pgdata
restart: unless-stopped
# DSpace Solr (search/statistics cores)
dspacesolr:
container_name: dspace-10.1-solr
image: docker.io/dspace/dspace-solr:dspace-10.1
environment:
MEM: 256m
networks:
- dspacenet
working_dir: /var/solr/data
volumes:
- solr_data:/var/solr/data
user: root
entrypoint:
- /bin/bash
- '-c'
- |
init-var-solr
precreate-core authority /opt/solr/server/solr/configsets/authority
cp -r /opt/solr/server/solr/configsets/authority/* authority
precreate-core oai /opt/solr/server/solr/configsets/oai
cp -r /opt/solr/server/solr/configsets/oai/* oai
precreate-core search /opt/solr/server/solr/configsets/search
cp -r /opt/solr/server/solr/configsets/search/* search
precreate-core statistics /opt/solr/server/solr/configsets/statistics
cp -r /opt/solr/server/solr/configsets/statistics/* statistics
precreate-core qaevent /opt/solr/server/solr/configsets/qaevent
cp -r /opt/solr/server/solr/configsets/qaevent/* qaevent
precreate-core suggestion /opt/solr/server/solr/configsets/suggestion
cp -r /opt/solr/server/solr/configsets/suggestion/* suggestion
precreate-core audit /opt/solr/server/solr/configsets/audit
cp -r /opt/solr/server/solr/configsets/audit/* audit
chown -R solr:solr /var/solr
runuser -u solr -- solr-foreground
restart: unless-stopped
# DSpace REST backend (Spring Boot runnable jar)
dspace:
container_name: dspace-10.1-backend
image: docker.io/dspace/dspace:dspace-10.1
environment:
dspace__P__dir: /dspace
dspace__P__server__P__url: http://192.168.1.200:8139/server
dspace__P__ui__P__url: http://192.168.1.200:8139
dspace__P__server__P__ssr__P__url: http://dspace-10.1-backend:8080/server
db__P__url: jdbc:postgresql://dspace-10.1-db:5432/dspace
solr__P__server: http://dspace-10.1-solr:8983/solr
proxies__P__trusted__P__ipranges: 10.89.58
LOGGING_CONFIG: /dspace/config/log4j2-container.xml
JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m
networks:
- dspacenet
volumes:
- assetstore:/dspace/assetstore
depends_on:
- dspacedb
- dspacesolr
entrypoint:
- /bin/bash
- '-c'
- |
while (!</dev/tcp/dspace-10.1-db/5432) > /dev/null 2>&1; do sleep 1; done;
/dspace/bin/dspace database migrate
java -jar /dspace/webapps/server-boot.jar
restart: unless-stopped
# DSpace Angular UI (production dist image)
dspace-angular:
container_name: dspace-10.1-ui
image: docker.io/dspace/dspace-angular:dspace-10.1-dist
environment:
DSPACE_UI_SSL: "false"
DSPACE_UI_HOST: dspace-10.1-ui
DSPACE_UI_PORT: "4000"
DSPACE_UI_NAMESPACE: /
DSPACE_UI_BASEURL: http://192.168.1.200:8139
DSPACE_REST_SSL: "false"
DSPACE_REST_HOST: 192.168.1.200
DSPACE_REST_PORT: "8139"
DSPACE_REST_NAMESPACE: /server
DSPACE_REST_SSRBASEURL: http://dspace-10.1-backend:8080/server
NODE_OPTIONS: --max-old-space-size=512
networks:
- dspacenet
depends_on:
- dspace
restart: unless-stopped
# Single public entry point: reverse proxy exposing UI (/) and REST (/server) on host port 8139
dspace-proxy:
container_name: dspace-10.1-proxy
image: docker.io/nginx:1.27-alpine
networks:
- dspacenet
ports:
- "8139:80"
volumes:
- ./nginx/dspace.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- dspace-angular
restart: unless-stopped
逐段解读:
- 网络:
ipam固定子网 10.89.58.0/24。多组件同机共存时给每套栈固定网段,避免 DHCP 漂移与互踩(本例占用 58 号网槽)。 - dspacedb:库/用户/口令三元组 dspace/dspace/dspace(演示口令,生产必改);
PGDATA=/pgdata配合命名卷,数据与安装态分离。 - dspacesolr:官方
dspace-solr镜像不会自动建 core,因此 entrypoint 整段重写:init-var-solr初始化数据目录后,用precreate-core逐个预建 7 个 core 并把对应 configset 拷入,最后降权到 solr 用户前台运行。MEM: 256m控制 Solr 堆。这一段是 DSpace 检索栈编排区别于通用 Solr 编排的核心特征,漏任何一个 core,后端对应功能(检索/统计/OAI/审计等)启动即报错。 - dspace(后端):
dspace__P__xxx形式的变量名是 DSpace 环境变量注入约定:__P__翻译为点号、__D__翻译为短横线,即db__P__url就是配置项db.url(详见配置篇);- entrypoint 三步:先以
/dev/tcp探测数据库端口就绪,再执行dspace database migrate建库/迁移,最后java -jar server-boot.jar起 REST 服务——数据库迁移自动内嵌在启动序列里,升级换标签后重启即完成迁移; LOGGING_CONFIG指向log4j2-container.xml(控制台日志形态);JAVA_TOOL_OPTIONS为堆治理入口(见第七节)。
- dspace-angular(前端):
DSPACE_UI_*/DSPACE_REST_*两组变量描述"浏览器看到的 UI 地址"与"REST 入口地址";注意DSPACE_REST_HOST/PORT指向的是宿主入口 192.168.1.200:8139 而非后端内部地址——浏览器侧发起的 API 请求必须走统一入口,SSR 服务端渲染则经DSPACE_REST_SSRBASEURL直连后端内部 8080,两条路径分离是官方 SSR 架构的关键。 - dspace-proxy:nginx 只读挂载单文件配置(见第五节),全栈唯一端口映射 8139:80。
五、反向代理统一入口
nginx/dspace.conf 全文(照抄在跑配置):
server {
listen 80;
server_name _;
client_max_body_size 100M;
location /server/ {
proxy_pass http://dspace-10.1-backend:8080/server/;
proxy_set_header Host $http_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 X-Forwarded-Host $http_host;
}
location / {
proxy_pass http://dspace-10.1-ui:4000;
proxy_set_header Host $http_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 X-Forwarded-Host $http_host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
要点:
- 一个域名/端口承载两个命名空间:
/server/前缀给 REST 后端,其余全部给 Angular UI——这正是 DSpace 官方推荐的"同域入口"形态,前端不需要跨域配置,Cookie(XSRF/会话)天然同域; client_max_body_size 100M放开大文件上传上限(默认 1M 会让比特流上传直接 413);- UI 段带
Upgrade/Connection头,支持 Angular 的 websocket 通道; - 后端侧配套
proxies.trusted.ipranges: 10.89.58,信任本网段的 X-Forwarded-For,保证统计与审计记录真实来源 IP。
六、启动与初始化实录
6.1 拉起与状态
docker compose up -d
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
dspace-10.1-backend docker.io/dspace/dspace:dspace-10.1 "/bin/bash -c 'while…" dspace 40 minutes ago Up 39 minutes 8000/tcp, 8080/tcp
dspace-10.1-db docker.io/postgres:15 "docker-entrypoint.s…" dspacedb 57 minutes ago Up 57 minutes 5432/tcp
dspace-10.1-proxy docker.io/nginx:1.27-alpine "/docker-entrypoint.…" dspace-proxy 57 minutes ago Up 57 minutes 0.0.0.0:8139->80/tcp, [::]:8139->80/tcp
dspace-10.1-solr docker.io/dspace/dspace-solr:dspace-10.1 "/bin/bash -c 'init-…" dspacesolr 57 minutes ago Up 57 minutes 8983/tcp
dspace-10.1-ui docker.io/dspace/dspace-angular:dspace-10.1-dist "pm2-runtime start d…" dspace-angular 57 minutes ago Up 57 minutes 4000/tcp
宿主监听确认(ss -lntp | grep 8139):
LISTEN 0 4096 0.0.0.0:8139 0.0.0.0:*
LISTEN 0 4096 [::]:8139 [::]:*
6.2 数据库迁移(entrypoint 自动执行)
后端日志开头实录:
Database URL: jdbc:postgresql://dspace-10.1-db:5432/dspace
Migrating database to latest version... (Check dspace logs for details)
Done.
Picked up JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m
2026-11-01 13:07:51,651 INFO unknown unknown org.hibernate.validator.internal.util.Version @ HV000001: Hibernate Validator 8.0.5.Final
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.5.16)
迁移结果核验(连库数表):
64
即 dspace database migrate 建出 64 张核心表(元数据值、DspaceObject、组/策略、工作流、社区/收藏层级等)。
6.3 创建管理员账号
迁移只建表不建账号,管理员用官方 CLI create-administrator 创建。交互提示流实录(依次输入邮箱、名、姓、确认 y、两次口令):
Creating an initial administrator account
E-mail address: First name: Last name: Is the above data correct? (y or n): Password will not display on screen.
Password:
Again to confirm:
Administrator account created
本例创建 admin@dspace.local(口令 q1w2e3r4,演示用);为验证可重复性又建了第二账号 demo-admin@dspace.local,随后经 REST 登录实测 HTTP 200。库内账号核验:
admin@dspace.local
demo-admin@dspace.local
⚠️ 该命令要求真实终端(TTY),无终端直接管道喂输入会报
Exception: Cannot invoke "java.io.Console.readLine()" because "console" is null,排障见第十节问题 1。
6.4 Solr core 核验
检索栈数据目录实测清单:
audit
authority
oai
qaevent
search
statistics
suggestion
7 个 core 与第四节预建清单一一对应。
七、JVM 堆治理(256–512MB)
官方后端启动默认不设堆上限、CLI 启动器(ScriptLauncher)自带 -Xmx2000m,小内存主机必须显式治理。修改位置就是 compose 后端服务的 environment:
JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m
生效验证一:后端日志首行出现拾取记录(6.2 节实录):
Picked up JAVA_TOOL_OPTIONS: -Xms256m -Xmx512m
生效验证二:进程级 jps -lv 实测回显(主进程 pid 1):
1 server-boot.jar -Xms256m -Xmx512m
同机各进程堆预算一览(实测):后端 256–512m、前端 Node --max-old-space-size=512、Solr MEM=256m、PostgreSQL 默认——整栈 2GB 内存主机可稳定运行。
💡 技术拓展:
JAVA_TOOL_OPTIONS与JAVA_OPTS取舍——前者是 JVM 原生识别的通用变量(任何java启动都会拾取并打印 Picked up 行),对官方镜像里"entrypoint 直接java -jar"的形态最稳;JAVA_OPTS只有启动脚本引用它时才生效。DSpace CLI 那条-Xmx2000m来自安装目录bin/dspace脚本自身,与后端堆相互独立:跑database migrate、index-discovery等大任务时若受 2GB 上限限制,可在执行环境单独覆盖 CLI 的堆参数,不必放大常驻后端。
八、端到端验证
- UI 首页:
curl -sI http://127.0.0.1:8139/
HTTP/1.1 200 OK
Server: nginx/1.27.5
Content-Type: text/html; charset=utf-8
Content-Length: 114298
X-Powered-By: Express
RateLimit-Policy: 500;w=60
RateLimit-Limit: 500
页面标题实测:<title>DSpace Repository :: Home</title>。
- REST 入口:
curl -s http://127.0.0.1:8139/server/api
{
"dspaceUI" : "http://192.168.1.200:8139",
"dspaceName" : "DSpace via local.cfg",
"dspaceServer" : "http://192.168.1.200:8139/server",
"dspaceVersion" : "DSpace 10.1",
"type" : "root",
...
}
dspaceVersion: DSpace 10.1 与第二节版本线核对一致;dspaceName 显示 local.cfg 生效值,其优先级链实验见配置篇。
- 登录链路(细节见 API 篇):
POST /server/api/authn/login实测HTTP/1.1 200并返回Authorization: Bearer <JWT>响应头。
九、持久化、升级与日常运维
持久化三卷:pgdata(结构化数据)、assetstore(比特流文件)、solr_data(索引与统计)。备份策略:pg_dump + assetstore 打包为权威组合,Solr 索引可全量重建(index-discovery CLI)不必纳入备份。
一个易踩的坑:配置覆写文件 local.cfg 若直接写入运行实例的可写层,重建(recreate)即丢失——优先级实验实测:删除环境变量并重建后,dspaceName 立刻回落到 dspace.cfg 出厂值 "DSpace at My University"。生产形态应把 local.cfg 以挂载方式固化(见配置篇)。
升级流程:改三处 dspace-10.x 标签 → docker compose up -d(自动重建)→ 后端 entrypoint 自动 database migrate → 验证 6.2/第八节。跨大版本(如 9→10)先读官方升级说明并全量备份。
日常运维命令速查:
| 操作 | 命令 |
|---|---|
| 查看栈状态 | docker compose ps |
| 跟踪后端日志 | docker compose logs -f dspace |
| 重启后端 | docker compose restart dspace |
| 进入后端执行 CLI | docker compose exec dspace /dspace/bin/dspace <command> |
| 停栈(保留数据) | docker compose down |
| 连库 | docker compose exec dspacedb psql -U dspace -d dspace |
十、排障实录
问题 1:create-administrator 无终端即崩
现象:管道喂输入执行 /dspace/bin/dspace create-administrator,回显:
Creating an initial administrator account
E-mail address: Exception: Cannot invoke "java.io.Console.readLine()" because "console" is null
java.lang.NullPointerException: Cannot invoke "java.io.Console.readLine()" because "console" is null
at org.dspace.administer.CreateAdministrator.negotiateAdministratorDetails(CreateAdministrator.java:159)
原因:该 CLI 用 System.console() 读交互输入,非 TTY 环境 console 为 null。解决:给命令分配伪终端。实测方案(宿主执行,成功回显见 6.3):
printf 'admin@dspace.local\nDemo\nAdmin\ny\nq1w2e3r4\nq1w2e3r4\n' | \
docker compose exec -T dspace bash -c \
"script -qec '/dspace/bin/dspace create-administrator' /dev/null"
注意提示顺序是 邮箱→名→姓→确认(y/n)→口令→重复口令,确认项漏填 y 会整体重来(实测循环两轮)。
问题 2:登录 403,不是 401
不带 X-XSRF-TOKEN 头直接 POST 登录,实测 HTTP 403(凭据正确也一样)。DSpace 的 CSRF 防护要求"Cookie + 同名请求头"成对出现,先 GET 任意 API 拿 DSPACE-XSRF-COOKIE,再原样回填请求头。完整流程与回显见 API 篇。
问题 3:重建后配置"回退"
即第九节 local.cfg 丢失坑:可写层改动不随卷持久化,up -d --force-recreate 后一切覆写消失。表现是"配置改过又变回去了",先查改动落在哪一层(env/挂载卷/可写层),优先级链实验方法见配置篇。
问题 4:默认配置全指向 localhost
出厂 dspace.cfg 实测关键项:
dspace.server.url = http://localhost:8080/server
dspace.ui.url = http://localhost:4000
db.url = jdbc:postgresql://localhost:5432/dspace
solr.server = http://localhost:8983/solr
多服务编排下这些 localhost 全部无效(各自指自己),必须用 db__P__url、solr__P__server、dspace__P__server__P__url 等环境变量覆盖——这就是第四节 env 清单的由来。
问题 5:Solr core 缺失导致后端起不来
官方 dspace-solr 镜像无自动建 core 逻辑,直接起裸 Solr 会让后端在 statistics/search 等 core 上报错。解法即第四节 entrypoint 的 precreate-core 预建清单。
问题 6:找 OpenAPI 契约 404
GET /server/v3/api-docs 实测 404:
{"type":"about:blank","title":"Not Found","status":404,"detail":"No static resource v3/api-docs.","instance":"/server/v3/api-docs"}
10.1 后端不发布 OpenAPI 端点;API 契约就是 HAL 超媒体本身,从 /server/api 根逐链接发现(见 API 篇)。
十一、部署检查清单
-
docker compose ps五服务全部 Up,仅 proxy 映射宿主端口 -
ss -lntp宿主监听 8139 - 后端日志出现
Migrating database to latest version... Done.且 Spring Boot banner 正常 - 数据库 64 表就位;
create-administrator成功且登录返回 200 - Solr 数据目录 7 core 齐全
-
jps -lv后端进程带-Xms256m -Xmx512m - UI 首页 200、
/server/api回显dspaceVersion: DSpace 10.1 -
proxies.trusted.ipranges与专用网段一致 - 三个命名卷 + local.cfg 挂载固化
- 生产加固:口令更换、HTTPS、备份计划
十二、参考链接
- DSpace/DSpace GitHub(Releases 版本线取证,查询日期 2026-11-01):https://github.com/DSpace/DSpace/releases
- DSpace 官方文档 DSDOC10x(Docker/安装章节,查询日期 2026-11-01):https://wiki.lyrasis.org/display/DSDOC10x
- Docker Hub dspace 命名空间(镜像标签口径,查询日期 2026-11-01):https://hub.docker.com/u/dspace
- 站内:《DSpace 介绍与选型指南》
- 站内:《DSpace 配置参数详解(env/local.cfg/dspace.cfg 三层优先级链与关键项)》
- 站内:《DSpace REST API 使用详解(HAL 超媒体认证、CRUD 与检索实测)》
- 站内同类部署实录对照:《EPrints 3.4.7 Ubuntu 22.04 安装部署指南》