OpenProject 迁移到 PostgreSQL 17 全指南:四种安装方式升级实操与排错
2026/9/14 22:55:27 网站建设 项目流程

OpenProject 迁移到 PostgreSQL 17 全指南:四种安装方式升级实操与排错

【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject

OpenProject 16 及以上版本已将 PostgreSQL 17 作为默认数据库,若你已有一套存量 OpenProject 实例,需要按本指南将数据库从旧版本(典型为 PostgreSQL 13)平滑升级到 17。本文以官方迁移文档为主体,结合仓库中的 docker-compose.yml(其dbdb-test服务均默认使用postgres:17镜像)等源码证据,完整覆盖 Docker Compose、Docker All-in-One、DEB/RPM 包安装与 Helm Chart 四种部署形态的升级步骤、恢复验证与常见故障处理。

迁移前须知:为什么需要升级到 PostgreSQL 17

OpenProject 16+ 默认使用 PostgreSQL 17。官方迁移文档明确指出:暂时仍然可以使用旧版 PostgreSQL,但不被推荐。这意味着虽然旧版本(如 13)还能运行,但新功能、性能优化与安全修复都围绕 PostgreSQL 17 展开,长期停留在旧版本会逐步偏离官方测试矩阵。

升级数据库是一个不可逆性较高的操作,因此有两个先决条件:

  1. 仅限相应安装方式:文档针对每种安装方式都强调"仅当你是通过该方式安装 OpenProject 时才适用",请对号入座,不要混用步骤。
  2. 必须先做备份:任何升级之前,务必先按照备份指南完成一次完整备份(数据库、配置文件、附件、仓库等)。

两种升级技术路线:SQL 转储 vs 原地升级

官方文档提供两种升级思路:

  • SQL 转储方式(本指南主体):用pg_dump导出数据,启动全新的 PostgreSQL 17 实例,再psql导入。优点是路径清晰、可控性强,也便于切换数据目录/卷。
  • 原地升级(in-place,pg_upgrade:PostgreSQL 官方提供的pgupgrade工具可以在同一数据目录上就地升级,文档允许你自由选择,但本文不展开其细节,如需使用请参考 PostgreSQL 官方文档。

两种方式都需要在升级完成后重建统计信息(见后文"升级后重建查询计划"一节)。


一、Docker Compose 安装方式的升级

本小节仅适用于通过 Docker Compose 安装流程 部署 OpenProject 的用户。开始前请确认已按备份指南完成备份。

第 1 步:备份当前 PostgreSQL 数据库

在 OpenProject 项目目录下执行:

docker compose exec -it -u postgres db pg_dump -d openproject -x -O > openproject.sql

这条命令会在当前目录生成备份文件openproject.sql。参数含义:

  • -d openproject:指定要导出的数据库名(OpenProject 默认数据库名);
  • -x--no-privileges):不导出权限(GRANT/REVOKE)语句,避免在新库导入时因角色差异报错;
  • -O--no-owner):不导出对象属主信息,导入时统一归当前连接用户所有;
  • -u postgres:以容器内的postgres系统用户执行pg_dump(Compose 中数据库容器默认使用postgres:17镜像,见仓库根目录 docker-compose.yml 中db服务的定义)。

第 2 步:停止 OpenProject 全部服务

docker compose down

停掉所有容器,确保升级期间没有新写入,保证备份数据的一致性和完整性。

第 3 步:为 PostgreSQL 17 准备覆盖配置

升级到 PostgreSQL 17 需要覆盖默认的数据库镜像,并定义一个新的数据卷,避免覆盖现有数据。

在 docker compose 目录下创建docker-compose.override.yml

volumes: pgdata17: services: db: image: postgres:17 volumes: - pgdata17:/var/lib/postgresql/data

要点解析:

  • Compose 会自动合并docker-compose.ymldocker-compose.override.yml,因此你不需要修改原 compose 文件;
  • db服务镜像替换为postgres:17
  • 关键点是新卷pgdata17:原有pgdata卷仍保存着旧版(如 13)的数据目录,若不换卷,新容器启动时会尝试读取旧版本格式的数据目录而失败,或者更糟——直接复用导致新旧格式冲突。换新卷后,新容器将获得一个全新的空数据目录。

第 4 步:启动新的数据库容器

docker compose up db -d

此时只启动数据库服务,得到一个数据目录为空的干净 PostgreSQL 17 容器。

第 5 步:把备份恢复到 PostgreSQL 17

docker compose exec -T -u postgres db psql -d openproject < openproject.sql

注意这里与备份命令的差异:

  • 使用-T而非-it-T关闭 TTY 分配,保证 stdin 重定向(< openproject.sql)能正确工作;
  • psql -d openproject会连接到新容器中由镜像初始化时自动创建的openproject数据库,并执行备份文件中的全部 SQL,完成数据导入。

第 6 步:启动完整的 OpenProject 服务栈

docker compose up -d

数据恢复完成后,把所有 OpenProject 服务(backend、worker、frontend 等)一起拉起。

验证

在浏览器中访问你的 OpenProject 实例,确认登录、项目列表、工作包等一切正常。确认无误后,即可按需清理旧的pgdata卷(例如docker volume rm),不过建议在观察一段时间后再清理。


二、Docker All-in-One 单容器方式的升级

本小节仅适用于通过 Docker 安装指南中的 All-in-One 容器方式 部署的用户。开始前请先完成备份。

注意:这种方式仅适用于 OpenProject >= 16.2 的版本,因为更早版本的 All-in-One 镜像默认内置的是 PostgreSQL 13。

All-in-One 容器把 OpenProject 应用、PostgreSQL、memcached 全部打进同一个容器,因此升级思路是:备份 → 停旧容器 → 起一个独立 PostgreSQL 17 容器恢复数据 → 用新数据卷重新启动 OpenProject 容器。

第 1 步:备份现有数据库

docker exec -it $OP_CONTAINER_NAME su - postgres -c 'pg_dump -d openproject -x -O' > openproject.sql

其中$OP_CONTAINER_NAME是你的 OpenProject 容器名(不知道可用docker ps | grep openproject查询)。命令在容器内切换为postgres用户执行pg_dump,把 SQL 输出重定向到宿主机上的openproject.sql文件。

第 2 步:停止 OpenProject 容器

docker stop $OP_CONTAINER_NAME

第 3 步:启动一个全新的 PostgreSQL 17 容器

docker run --rm -d --name postgres \ -e POSTGRES_PASSWORD=postgres \ -e LANG=C.UTF-8 \ -e LC_ALL=C.UTF-8 \ -v /var/lib/openproject/pgdata17:/var/lib/postgresql/data \ postgres:17

说明:

  • --rm:容器停止后自动删除(临时迁移容器);
  • -e POSTGRES_PASSWORD=postgres:设置超级用户密码;
  • -e LANG/LC_ALL:设置 UTF-8 环境,避免编码问题;
  • -v /var/lib/openproject/pgdata17:/var/lib/postgresql/data:把宿主机新目录挂载为数据目录——与 Docker Compose 方式同理,使用全新路径避免覆盖旧数据。

第 4 步:创建 OpenProject 数据库用户

连接新容器,创建openproject用户:

echo "CREATE USER openproject WITH PASSWORD 'openproject';" | docker exec -i postgres psql -U postgres

文档原步骤描述为"drop the openproject database",即确保目标库不存在;若镜像初始化时自动创建的同名库存在,可在执行前先用DROP DATABASE openproject;清理,再继续后续创建。

第 5 步:创建新的数据库

echo "CREATE DATABASE openproject OWNER openproject;" | docker exec -i postgres psql -U postgres

新建的openproject数据库属主为openproject用户,与备份中的对象归属保持一致。

第 6 步:从转储恢复数据库

docker exec -i postgres psql -U openproject -d openproject < openproject.sql

openproject用户身份把备份导入新数据库。由于备份使用了-x -O,导入过程不会因为权限/属主语句而报错。

第 7 步:停止 PostgreSQL 容器

docker stop postgres

第 8 步:用 PostgreSQL 17 重新启动 OpenProject

docker run -d -p 8080:80 --name openproject \ -e OPENPROJECT_HOST__NAME=openproject.example.com \ -e SECRET_KEY_BASE=<your-secret-key-base> \ -v /var/lib/openproject/pgdata17:/var/openproject/pgdata \ -v /var/lib/openproject/assets:/var/openproject/assets \ openproject/openproject:17

关键点:

  • 数据卷挂载从原来的/var/lib/openproject/pgdata换成了升级后的pgdata17
  • SECRET_KEY_BASE必须与旧实例保持一致,否则会话与加密的数据库内容将无法解密;
  • OPENPROJECT_HOST__NAME、镜像版本等环境变量请与你原有配置保持一致。

验证

访问你的 OpenProject 实例,确认功能正常。


三、DEB/RPM 包安装方式的升级

本小节仅适用于通过包安装方式(packaged) 部署的用户。开始前请先完成备份。

包安装方式下的 PostgreSQL 由系统服务管理,升级涉及新旧集群的启停、配置文件迁移与旧版本卸载,步骤最多,需格外谨慎。

第 1 步:停止 OpenProject

sudo service openproject stop

第 2 步:备份数据库

pg_dump $(sudo openproject config:get DATABASE_URL) -x -O > openproject.sql

sudo openproject config:get DATABASE_URL直接读取 OpenProject 配置中保存的连接串,pg_dump据此连接并导出,同样带-x -O参数。

第 3 步:停止现有 PostgreSQL

Debian/Ubuntu(Debian 系用pg_ctlcluster管理集群,典型为 13 版main集群):

sudo pg_ctlcluster 13 main stop

CentOS/RHEL 与 SLES(RHEL 系用 systemd 服务):

sudo systemctl stop postgresql-13

第 4 步:安装 PostgreSQL 17

Debian/Ubuntu

sudo apt update sudo apt install postgresql-17 sudo pg_createcluster 17 main --start

pg_createcluster 17 main --start创建新的 17 版本main集群并立即启动。

CentOS/RHEL

sudo dnf install -y postgresql17-server postgresql17-contrib sudo /usr/pgsql-17/bin/postgresql-17-setup initdb sudo systemctl enable --now postgresql-17

SLES:文档给出的命令带有TODO标记,属于尚待完善的部分,核心思路是添加 PostgreSQL 官方 zypper 仓库后安装并启动服务:

# TODO: sudo zypper addrepo https://download.postgresql.org/pub/repos/zypp/17/suse/sles-15.5-x86_64/ openSUSE-PostgreSQL-17 # TODO: sudo zypper install --repo openSUSE-PostgreSQL-17 postgresql17 postgresql17-server postgresql17-libs postgresql17-contrib # TODO:? sudo su - postgres -c '/usr/lib/postgresql17/bin/initdb -D /var/lib/pgsql/17/data' sudo systemctl enable postgresql sudo systemctl start postgresql

该部分在官方文档中标注为 TODO,实际操作时请以你所用 SLES 版本的 PostgreSQL 官方安装说明为准。

第 5 步:复制配置文件

升级后需要把旧版本的认证与自定义配置带到新版本,避免因默认配置差异导致连接行为变化。

Debian/Ubuntu

sudo su - postgres -c "cp /etc/postgresql/13/main/pg_hba.conf /etc/postgresql/17/main/pg_hba.conf" sudo su - postgres -c "cp /etc/postgresql/13/main/conf.d/custom.conf /etc/postgresql/17/main/conf.d/custom.conf" sudo pg_ctlcluster 17 main restart

CentOS/RHEL

sudo su - postgres -c "cp /var/lib/pgsql/13/data/pg_hba.conf /var/lib/pgsql/17/data/pg_hba.conf" sudo su - postgres -c "cp -r /var/lib/pgsql/13/data/conf.d /var/lib/pgsql/17/data/" sudo su - postgres -c "cp -r /var/lib/pgsql/13/data/postgresql.conf /var/lib/pgsql/17/data/postgresql.conf" sudo service postgresql-17 restart

SLES

sudo su - postgres -c "cp /var/lib/pgsql/13/data/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf" sudo su - postgres -c "cp -r /var/lib/pgsql/13/data/conf.d /var/lib/pgsql/data/" sudo su - postgres -c "cp -r /var/lib/pgsql/13/data/postgresql.conf /var/lib/pgsql/data/postgresql.conf" sudo systemctl restart postgresql

注意:第 6 步中的故障排查部分会提到,复制过来的pg_hba.conf中如果含有scram-sha-256认证方式,可能导致旧凭据认证失败,需要视情况改回md5(详见"故障排查")。

第 6 步:移除旧版 PostgreSQL

Debian/Ubuntu

sudo apt remove --purge postgresql-13

CentOS/RHEL

sudo dnf remove postgresql13-server

SLES

sudo zypper remove postgresql13-server

第 7 步:重建 OpenProject 用户与数据库

sudo su - postgres -c "psql -p 45432 -c \"create user openproject with password '$(sudo openproject config:get DATABASE_URL | sed -n 's|.*://[^:]*:\([^@]*\)@.*|\1|p')'\"" sudo su - postgres -c "psql -p 45432 -c 'create database openproject owner openproject'"

这里有两个值得展开的细节:

  • 端口45432:OpenProject 包安装通常为 PostgreSQL 配置独立的监听端口(而非默认 5432),以隔离实例;请以你环境实际的端口为准;
  • 密码提取:第一条命令用sedDATABASE_URL连接串中正则提取密码部分(s|.*://[^:]*:\([^@]*\)@.*|\1|p),确保重建的openproject用户密码与应用配置完全一致。

第 8 步:恢复数据库

psql $(sudo openproject config:get DATABASE_URL) < openproject.sql

通过应用自身的DATABASE_URL连接新集群并导入数据。

第 9 步:重启 OpenProject

sudo openproject restart

验证

浏览器访问实例确认一切正常。


四、Helm Chart(Kubernetes)安装方式的升级

本小节仅适用于通过 Helm Chart 部署 OpenProject 的用户(可参考 Kubernetes 安装说明,该文指向 OpenProject 官方 Helm Chart)。开始前请先完成备份。

Helm 方式下数据库是独立的 Bitnami PostgreSQL Pod,升级思路是:缩容前端 → 在 Pod 内pg_dumpall备份 → 重命名数据目录 → 升级镜像 tag → 恢复 → 扩容前端。

第 1 步:缩容前端

停止前端或将其副本缩到 0,防止升级期间前端产生新的写操作:

kubectl scale deployment <frontend-deployment> --replicas=0

第 2 步:备份数据库

进入现有 PostgreSQL Pod 的 shell:

kubectl exec -it <postgresql-pod-name> -- bash

在 Pod 内生成全库转储(pg_dumpall同时导出角色与所有数据库)并保存到持久化目录:

PGPASSWORD=$(cat "${POSTGRES_POSTGRES_PASSWORD_FILE:-/dev/null}" && echo "$POSTGRES_POSTGRES_PASSWORD") pg_dumpall -U postgres > /bitnami/postgresql/backup.sql

第 3 步:重命名旧数据目录

把当前数据目录改名保留,一旦升级出现问题可以回滚:

mv /bitnami/postgresql/data /bitnami/postgresql/data-old

第 4 步:升级 Bitnami PostgreSQL 版本

values.yaml中追加以下内容,指定 PostgreSQL 17 的镜像 tag:

postgresql: image: tag: 17.5.0-debian-12-r16

示例 tag 为文档给出的版本,实际部署时请选择与你环境兼容的 Bitnami PostgreSQL 17 镜像 tag。

第 5 步:恢复数据库

应用新 values 完成 Chart 升级后,进入新 PostgreSQL Pod:

kubectl exec -it <new-postgresql-pod-name> -- bash

执行恢复:

PGPASSWORD=$(cat "${POSTGRES_POSTGRES_PASSWORD_FILE:-/dev/null}" && echo "$POSTGRES_POSTGRES_PASSWORD") psql -U postgres -h localhost -f /bitnami/postgresql/backup.sql

第 6 步:恢复前端

启动前端或将其扩容回原副本数。

第 7 步:验证升级

确认 PostgreSQL 实例运行正常、前端可访问、业务数据完整。

第 8 步:清理备份文件

验证通过后,再次进入 PostgreSQL Pod 删除备份与旧数据目录:

rm /bitnami/postgresql/backup.sql rm -r /bitnami/postgresql/data-old

升级后:重建表查询计划(强烈建议)

PostgreSQL 升级后,统计信息与查询计划不会必然自动重建,官方文档强烈建议执行以下 SQL 命令强制重新生成,否则可能出现旧统计信息导致的性能劣化(例如执行计划退化)。

先打开数据库控制台。以包安装方式为例:

psql $(openproject config:get DATABASE_URL)

其他安装方式请相应调整连接命令(如 Docker Compose 可docker compose exec -T -u postgres db psql -d openproject)。连接后执行:

ANALYZE VERBOSE;

ANALYZE会重新采集所有表的统计信息,VERBOSE输出处理明细便于确认执行范围。这一步对任何升级方式(包括pg_upgrade)都适用。


故障排查:SCRAM 认证失败

升级后可能遇到如下报错:

User "openproject" does not have a valid SCRAM secret - psql: error: FATAL: password authentication failed for user "openproject"

原因:旧版本数据库的用户口令可能基于md5存储,而新集群的认证配置(通常是从旧版本复制过来的pg_hba.conf或新版本默认的postgresql.conf)要求scram-sha-256,导致口令格式不匹配、认证失败。

处理步骤:

  1. 检查/var/lib/pgsql/17/data/pg_hba.conf,把其中出现的scram-sha-256替换为md5
  2. 检查/var/lib/pgsql/17/data/postgresql.conf,搜索encryption(即password_encryption相关配置),把scram-sha-256同样替换为md5
  3. 重新加载 PostgreSQL 配置使其生效:
systemctl reload postgresql-17

说明:scram-sha-256是比md5更安全的认证机制。上述改回md5是官方文档给出的兼容性处理,解决升级窗口期的认证问题;如需更高安全性,可在确认数据与口令迁移正常后,为openproject用户重新设置口令并切回scram-sha-256,但这属于超出本文范围的加固步骤。


常见疑问与最佳实践小结

  • 为什么备份命令都带-x -O-x跳过 GRANT/REVOKE 权限语句、-O跳过属主设置,两者都避免在目标集群角色不同时导入报错,是"跨集群迁移"的标准做法;Helm 场景使用pg_dumpall则是为了连角色一起迁移。
  • 为什么 Docker 方式要新建数据卷/目录?PostgreSQL 的数据目录格式与主版本强绑定,复用旧目录会导致新旧格式冲突。新建卷(pgdata17)后,新实例从空目录初始化,数据完全依靠 SQL 导入。
  • 升级前备份、升级后ANALYZE VERBOSE是两条不可省略的保险带:前者保证可回滚,后者保证性能不劣化。
  • 配置一致性:无论是 Docker 的SECRET_KEY_BASEOPENPROJECT_HOST__NAME,还是包安装的DATABASE_URL与端口,升级后必须与原实例保持一致,否则会出现会话失效、链接生成错误或连接失败。
  • 官方文档中关于本主题的完整原始内容位于 docs/installation-and-operations/misc/migration-to-postgresql17/README.md,安装与备份的配套资料可参考 Docker 安装说明、包安装说明与备份指南;仓库根目录 docker-compose.yml 也印证了当前开发环境已默认采用postgres:17,与本文升级目标一致。

【免费下载链接】openprojectOpenProject is the leading open source project management software for product, project and portfolio management. A powerful Jira alternative with agile planning, issue tracking, roadmaps, Gantt charts, time tracking, collaboration features, and more. Available on premises or in the cloud. ⭐ Star us on GitHub项目地址: https://gitcode.com/GitHub_Trending/op/openproject

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询