news 2026/10/5 1:54:24

Zenodo 本地安装与开发环境搭建指南:Docker 全栈部署与源码级开发实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Zenodo 本地安装与开发环境搭建指南:Docker 全栈部署与源码级开发实践
  • 后端
  • 企业应用

【免费下载链接】zenodo

Research. Shared.

项目地址:https://gitcode.com/gh_mirrors/ze/zenodo
点击查看免费下载

本指南围绕 Zenodo(CERN 开发的开源科研数据共享平台)的 INSTALL.rst 展开,系统讲解两种落地方式:一条是基于docker-compose的"全栈容器化"快速部署路径,适合只想本地运行验证的用户;另一条是"容器只跑依赖服务、代码跑在本机虚拟环境"的开发安装路径,适合后续要修改 Zenodo 源码的开发者。读完本文,你将掌握从零搭建 Zenodo 本地实例、初始化数据库与搜索索引、构建前端资源、启动 Celery 异步任务队列以及加载许可证等数据全过程的完整操作。

一、安装前必读:Zenodo 的运行时依赖

Zenodo 建立在 Invenio 框架之上,是一个典型的微服务化 Web 应用,运行它至少需要四类基础服务:

服务用途对应 docker-compose 服务名
PostgreSQL主数据库,存储记录、用户、元数据db
Elasticsearch全文检索与索引search/es
Redis缓存与 Celery 结果后端cache
RabbitMQ异步任务消息队列mq

INSTALL.rst 开头将依赖描述为 PostgreSQL、Elasticsearch 2.x、Redis 和 RabbitMQ;而在后文"运行服务"一节中又要求 Elasticsearch 7.x。结合当前仓库 docker-services.yml 的实际配置可以看到,搜索服务实际使用的是opensearchproject/opensearch:2.2.1镜像,并启用了compatibility.override_main_response_version=true以兼容 Elasticsearch 7.x 的响应格式。因此读者在搭建时应以仓库当前锁定的镜像为准,避免被文档中不一致的版本描述误导。

两种安装路径的差异在于"应用代码跑在哪里":

  • Docker 安装:应用、前端、负载均衡、监控全部容器化,一条命令拉起完整栈;
  • 开发安装:只把 PostgreSQL、Elasticsearch、Redis、RabbitMQ 跑在 Docker 里,Zenodo 应用代码与 Celery worker 跑在你自己创建的 Python 虚拟环境中,方便直接编辑代码、即时调试。

提示:若无法使用 Docker,也可以直接在本机系统安装这四个服务。此时应参照 docker-compose.yml 与 docker-services.yml 中声明的环境变量(如INVENIO_SQLALCHEMY_DATABASE_URI、INVENIO_BROKER_URL、INVENIO_SEARCH_ELASTIC_HOSTS等)来手动配置连接参数。

二、方式一:Docker 全栈安装(快速体验)

2.1 克隆代码并构建完整栈

全栈安装需要 Docker 与 docker-compose 工具。假设所有代码仓库都检出在~/src/目录下(下文均以此为前提),首先克隆 Zenodo 源码并切换到 master 分支:

$ cd ~/src/ $ git clone https://gitcode.com/gh_mirrors/ze/zenodo.git $ cd ~/src/zenodo $ git checkout master

接着使用完整栈配置文件 docker-compose.full.yml 构建镜像并后台启动:

$ docker-compose -f docker-compose.full.yml build $ docker-compose -f docker-compose.full.yml up -d

2.2 docker-compose.full.yml 的完整栈结构

从 docker-compose.full.yml 可以清晰看到 Zenodo 生产级部署的容器编排,全部服务均通过extends继承 docker-services.yml 中的基础定义:

容器角色关键配置
lbHAProxy 负载均衡映射宿主80/443/8080端口,前端链路指向frontend
frontendNginx 反向代理映射宿主81/444端口,代理到web,共享static容器的静态卷
webuWSGI 应用服务器命令uwsgi /code/zenodo/docker/uwsgi/uwsgi.ini,暴露5000端口,链接cache/search/mq/db四个基础服务
workerCelery 异步 worker命令celery worker -A zenodo.celery --loglevel=INFO,常驻运行(restart: "always")
static静态资源数据卷容器挂载static、site-packages、data与源码目录/code/zenodo
flowerCelery 任务监控暴露5555端口,链接mq
search-dashboardsOpenSearch Dashboards暴露5601端口,OPENSEARCH_HOSTS=http://search:9200

其中app基础服务的环境变量(见 docker-services.yml)揭示了 Zenodo 的配置注入方式——所有 Invenio 配置均可通过INVENIO_*环境变量覆盖,例如:

  • INVENIO_SQLALCHEMY_DATABASE_URI=postgresql://zenodo:zenodo@db/zenodo:数据库连接串,对应db容器中POSTGRES_USER=zenodo、POSTGRES_PASSWORD=zenodo、POSTGRES_DB=zenodo;
  • INVENIO_BROKER_URL=amqp://guest:guest@mq:5672//与INVENIO_CELERY_BROKER_URL:RabbitMQ 消息代理地址;
  • INVENIO_CACHE_REDIS_URL=redis://cache:6379/0与INVENIO_CELERY_RESULT_BACKEND=redis://cache:6379/2:Redis 缓存与 Celery 结果后端;
  • INVENIO_SEARCH_ELASTIC_HOSTS=['es:9200']:搜索服务地址;
  • INVENIO_SESSION_COOKIE_SECURE=True、INVENIO_WSGI_PROXIES=2、INVENIO_SECRET_KEY=CHANGE_ME(部署时务必替换密钥)。

2.3 初始化数据库、索引与演示数据

保持 docker-compose 会话存活,另开一个新终端,在web容器内运行仓库自带的初始化脚本 scripts/init.sh:

$ cd ~/src/zenodo $ docker-compose -f docker-compose.full.yml run --rm web bash /code/zenodo/scripts/init.sh

scripts/init.sh 的核心逻辑值得拆解——它依次执行了一整套 Zenodo CLI 命令:

zenodo db create # 创建数据库表结构 zenodo index queue init # 初始化索引队列 zenodo index init # 创建 Elasticsearch/OpenSearch 索引 zenodo queues declare # 声明 RabbitMQ 队列 zenodo fixtures init loadlicenses loadfunders loadfp6grants \ loadsipmetadatatypes loadusers loadcommunities # 加载许可证、资助方、FP6 资助项目、SIP 元数据类型、用户、社区等数据 zenodo index reindex -t od_lic -t frdoi -t grant --yes-i-know # 重建许可证/资助项目/资助方索引 zenodo index run # 消费索引队列

这也解释了为什么"初始化"这一步是异步、多阶段的:数据库建表与索引创建相互独立,而许可证(od_lic)、资助项目(frdoi)、资助方(grant)等索引需要先有数据再重建。

2.4 浏览器访问、监控界面与端口总览

初始化完成后,在浏览器访问:

https://<docker ip>
  • 在 Linux 以及较新的 macOS 上,<docker ip>通常就是localhost;
  • 在通过docker-machine运行 Docker 的旧版 macOS / Windows 上,用docker-machine ip <machine-name>查出实际 IP。

全栈部署还自带了三个监控/管理界面:

  • Elasticsearch 插件界面:http://<docker ip>:9200/_plugin/hq/
  • RabbitMQ 管理控制台:http://<docker ip>:15672/(默认账号guest/guest)
  • HAProxy 统计页:http://<docker ip>:8080/(默认账号guest/guest)

同时,Docker 宿主机上暴露了以下端口,可用于排查各组件连通性:

端口服务
80/443HAProxy(HTTP / HTTPS 入口)
81/444Nginx
5000Zenodo 应用
5432PostgreSQL
5672RabbitMQ
6379Redis
8080HAProxy stats
9200/9300Elasticsearch(HTTP / 传输层)
15672RabbitMQ management console

三、方式二:开发安装(容器跑依赖、本机跑代码)

开发安装的核心思路是复用 docker-compose.yml 只拉起四个基础服务(PostgreSQL、Elasticsearch、Redis、RabbitMQ),把 Zenodo 应用代码装进自己的 Python 虚拟环境,便于随时编辑与调试。

注意:由于 Docker 会把服务映射到本机localhost的默认端口,请确保系统里没有同端口占用——即本机不能同时运行 PostgreSQL、Redis、RabbitMQ 或 Elasticsearch。

3.1 仅启动四个基础服务

$ cd ~/src/zenodo $ docker-compose up -d # "-d" 表示后台运行

docker-compose.yml 中只声明了cache、db、mq、search四个服务(分别继承自 docker-services.yml),其中search额外挂载了名为search的本地数据卷以持久化搜索索引数据。

3.2 创建虚拟环境并安装依赖

使用 virtualenvwrapper 创建独立虚拟环境(注意仓库 Dockerfile 基于python:2.7,文档也以 Python 2.7 为例):

$ mkvirtualenv -p python2.7 zenodo (zenodo)$

关于 Python 版本:Zenodo 同时支持 Python 2.7 与 3.5+,但如果你需要用到 XRootD 存储接口,则必须使用 Python 2.7——因为底层 XRootD 库尚不支持 Python 3.5+。这一点同样反映在 Dockerfile 中:FROM python:2.7。

进入源码目录,安装 Python 依赖与 Zenodo 本体:

(zenodo)$ cd ~/src/zenodo (zenodo)$ pip install -r requirements.txt (zenodo)$ pip install -e ".[all]"

其中pip install -e ".[all]"以可编辑模式安装 Zenodo 及其全部可选依赖;Dockerfile 中对应的镜像内安装命令是pip install -e .[postgresql,elasticsearch2,all],可据此了解依赖分组(postgresql、elasticsearch2为不同的后端扩展组)。

3.3 前端资源构建(NodeJS / NPM 工具链)

Zenodo 前端资源不是预编译产物,而是由 SASS、JavaScript 等源文件经一系列构建工具现场编译生成,因此需要先安装 NodeJS 工具链。

版本要求

文档明确要求的工具版本如下:

工具版本
NodeJS7.4
NPM4.0.5
SASS(node-sass)3.8.0
CleanCSS3.4.19
UglifyJS2.7.3
RequireJS2.2.0

建议用 NVM(Node Version Manager,作用类似 Python 的 pyenv)安装并切换 Node 版本:

(zenodo)$ nvm install 7.4 (zenodo)$ nvm use 7.4 Now using node v7.4.0 (npm v4.0.5)

如果想长期使用 Node v7.4,可以设为默认版本,省去每次nvm use的麻烦:

(zenodo)$ nvm alias default 7.4
安装 npm 依赖

运行仓库提供的 scripts/setup-npm.sh,包会安装到当前用户的 NVM 环境中:

(zenodo)$ ./scripts/setup-npm.sh

该脚本的源码实现印证了版本约束的严谨性:它先检查node --version,只有匹配v7*或v6*才继续,否则直接报错退出;随后通过npm install --silent -g全局安装四个精确锁定版本的构建工具:node-sass@3.8.0、clean-css@3.4.19、uglify-js@2.7.3、requirejs@2.2.0。顺带说明,脚本开头还内嵌了一段"修复 npm 未安装"的兼容逻辑(对应历史 issue #2154),会直接下载 Node v7.4.0 的二进制包解压到/usr/local,这也是 Dockerfile 中镜像构建时直接执行该脚本的原因。

下载并编译前端资源

接下来运行 scripts/setup-assets.sh 完成前端资源的下载与编译:

(zenodo)$ ./scripts/setup-assets.sh

从脚本源码可以看到它做的事情远不止"编译":先再次校验 node 版本与四个构建工具二进制(cleancss、node-sass、uglifyjs、r_js)是否就位,然后依次执行:

zenodo npm --pinned-file package.pinned.json # 依据 package.pinned.json 生成实例静态目录下的 package.json cd ${VIRTUAL_ENV}/var/instance/static npm install # 安装前端 npm 依赖 zenodo collect -v # 收集各模块静态资源 zenodo assets build # 编译 SASS/JS,产出最终静态资源

其中package.pinned.json(仓库根目录)是前端依赖的锁定清单;zenodo assets build则调用 Invenio 的 webassets 机制把theme、records、deposit、search_ui等模块的scss与js编译为可对外服务的静态文件。

3.4 运行基础服务与初始化

在开发模式下同样需要四个基础服务在线,执行:

$ cd ~/src/zenodo $ docker-compose up -d

这会拉起 PostgreSQL(db)、Elasticsearch(es)、RabbitMQ(mq)、Redis(cache)四个容器,保持该终端会话存活。

接着在新的终端会话中激活虚拟环境并初始化数据库、搜索索引、消息队列及各类 fixtures(许可证、资助项目、社区、用户等):

$ cd ~/src/zenodo $ workon zenodo (zenodo)$ ./scripts/init.sh

关于./scripts/init.sh内部各条命令的含义,可回看本文 2.3 节的逐行拆解——开发安装与 Docker 安装走的是同一套初始化流程。

3.5 启动 Celery worker

Zenodo 的许多操作(索引、异步任务、外部数据收割)依赖 Celery,需要在另一个终端会话启动 worker:

$ cd ~/src/zenodo $ workon zenodo (zenodo)$ celery worker -A zenodo.celery -l INFO --purge

-A zenodo.celery指定 Celery 应用入口,即 zenodo/celery.py——它直接复用了 Invenio 提供的invenio_app.celery应用对象(from invenio_app.celery import celery),因此 Zenodo 的所有异步任务都注册在这同一个应用上;--purge会在启动前清空积压的过期任务消息。

3.6 加载外部数据(许可证等)

接下来加载演示数据——目前阶段只有许可证。由于加载过程需要向外部的 OAI-PMH 或 REST API 发起收割,因此依赖互联网,且必须保持 Celery worker 会话存活,然后在另一个终端执行:

$ cd ~/src/zenodo $ workon zenodo (zenodo)$ zenodo opendefinition loadlicenses -s opendefinition (zenodo)$ zenodo opendefinition loadlicenses -s spdx (zenodo)$ ./scripts/index.sh
  • 两条loadlicenses命令分别从 OpenDefinition 与 SPDX 两个来源收割许可证数据,由 Celery 异步执行;
  • scripts/index.sh 则承担索引重建任务,其内部逻辑为:
zenodo index destroy --force --yes-i-know # 删除旧索引 zenodo index init --force # 重新创建索引 zenodo index reindex -t od_lic -t frdoi -t grant -t recid -t depid --yes-i-know zenodo index run -c 4 -d # 以 4 个并发 worker 消费索引队列

注意开发安装的index.sh比 Docker 安装的init.sh多重建了recid(记录)与depid(deposit)两类索引,因为此时需要把已入库的记录数据也索引进搜索。

3.7 启动开发服务器

最后,以调试模式启动 Zenodo 开发服务器:

(zenodo)$ export FLASK_DEBUG=True (zenodo)$ zenodo run

访问http://localhost:5000,即可看到与生产环境(zenodo.org)同源同构的 Zenodo 实例页面。FLASK_DEBUG=True让 Flask 进入调试模式,代码改动会自动重载、出错时展示交互式调试页,极大方便源码开发调试。

四、DOI 徽章(Badges)的系统依赖

如果希望记录详情页上的 DOI 徽章(badge)正常工作,宿主系统还需要具备两个底层组件:

  • Cairo SVG 库:用于将 SVG 徽章渲染为图片;
  • DejaVu Sans 字体:徽章文本渲染所需的默认字体。

这正是 Dockerfile 在系统依赖安装阶段显式加入libcairo2-dev fonts-dejavu的原因——容器镜像在构建时就预置了这两项依赖。对本机开发安装而言,请确保你的操作系统装有libcairo2-dev(或对应发行版名称)与fonts-dejavu后再验证徽章功能。

五、小结:两种安装路径的选型建议

  • 只想本地体验 / 验证功能:选 Docker 全栈安装,docker-compose -f docker-compose.full.yml build && up -d加上一次init.sh即可拥有包含负载均衡、反向代理、Celery worker、监控面板的完整 Zenodo;
  • 打算二次开发 Zenodo 源码:选开发安装,用docker-compose.yml只跑四个基础服务,代码跑在 virtualenv 中,配合FLASK_DEBUG=True与 Celery worker 获得即时反馈的开发循环;
  • 无论哪种方式,都必须完整经历"启动依赖服务 →scripts/init.sh初始化 → 构建前端资源(开发模式)→ 加载许可证数据 → 重建索引"这几个阶段,任一环节缺失都会导致页面、搜索或异步任务异常。

上述所有命令与配置均取自当前仓库的 INSTALL.rst、docker-compose.full.yml、docker-compose.yml、docker-services.yml、Dockerfile 以及 scripts/init.sh、scripts/setup-npm.sh、scripts/setup-assets.sh、scripts/index.sh 等文件,可按需深入阅读以理解各环节的底层实现。

  • 后端
  • 企业应用

【免费下载链接】zenodo

Research. Shared.

项目地址:https://gitcode.com/gh_mirrors/ze/zenodo
点击查看免费下载

相关推荐

上一篇:Blockbench PBR材质实战:从零打造专业级金属与粗糙度效果
下一篇:OneDev配置管理终极指南:环境变量与密钥安全存储的7个专业技巧

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 1:48:36

规格驱动开发实战:用Codex从Spec到全栈应用的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:44:49

终极游戏存档守护指南:用Ludusavi让游戏进度永不丢失

终极游戏存档守护指南&#xff1a;用Ludusavi让游戏进度永不丢失 【免费下载链接】ludusavi Backup tool for PC game saves 项目地址: https://gitcode.com/GitHub_Trending/lu/ludusavi 作为一名游戏玩家&#xff0c;你是否曾因电脑重装、游戏崩溃或存档损坏而失去宝贵…

作者头像 李华