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(其db与db-test服务均默认使用postgres:17镜像)等源码证据,完整覆盖 Docker Compose、Docker All-in-One、DEB/RPM 包安装与 Helm Chart 四种部署形态的升级步骤、恢复验证与常见故障处理。
迁移前须知:为什么需要升级到 PostgreSQL 17
OpenProject 16+ 默认使用 PostgreSQL 17。官方迁移文档明确指出:暂时仍然可以使用旧版 PostgreSQL,但不被推荐。这意味着虽然旧版本(如 13)还能运行,但新功能、性能优化与安全修复都围绕 PostgreSQL 17 展开,长期停留在旧版本会逐步偏离官方测试矩阵。
升级数据库是一个不可逆性较高的操作,因此有两个先决条件:
- 仅限相应安装方式:文档针对每种安装方式都强调"仅当你是通过该方式安装 OpenProject 时才适用",请对号入座,不要混用步骤。
- 必须先做备份:任何升级之前,务必先按照备份指南完成一次完整备份(数据库、配置文件、附件、仓库等)。
两种升级技术路线: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.yml与docker-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.sqlsudo openproject config:get DATABASE_URL直接读取 OpenProject 配置中保存的连接串,pg_dump据此连接并导出,同样带-x -O参数。
第 3 步:停止现有 PostgreSQL
Debian/Ubuntu(Debian 系用pg_ctlcluster管理集群,典型为 13 版main集群):
sudo pg_ctlcluster 13 main stopCentOS/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 --startpg_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-17SLES:文档给出的命令带有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 restartCentOS/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 restartSLES:
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-13CentOS/RHEL:
sudo dnf remove postgresql13-serverSLES:
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),以隔离实例;请以你环境实际的端口为准; - 密码提取:第一条命令用
sed从DATABASE_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,导致口令格式不匹配、认证失败。
处理步骤:
- 检查
/var/lib/pgsql/17/data/pg_hba.conf,把其中出现的scram-sha-256替换为md5; - 检查
/var/lib/pgsql/17/data/postgresql.conf,搜索encryption(即password_encryption相关配置),把scram-sha-256同样替换为md5; - 重新加载 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_BASE、OPENPROJECT_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),仅供参考