Polarion-2506-Docker重建与ARM修复

目录

问题背景

前一篇《Polarion-2506-本地开发与30天试用》记录了 2506 的开发环境。Docker 负责安装、提取运行时,并提供 PostgreSQL/Apache。

Polarion Java 仍然由 Eclipse/PDE 启动。

这次重启 Docker 时,我曾经保留了下面三个容器:

1
2
3
polarion2506-services
polarion2506-services-recovery
polarion2506-services-recovery-before-t4-20260807

它们并不是三个独立的 Polarion 环境。三个容器使用相同的镜像、相同的 /opt/polarion 外置挂载目录、相同的 HTTP/数据库端口和同一套 PostgreSQL 数据目录,所以没有必要同时保留。

为什么三个容器都无法启动

三个容器的启动命令都是:

1
dependencies

逐个执行 docker start -a 时,最后都报:

1
PostgreSQL for Polarion service isn't running

Polarion 的 bin/postgresql-polarion.init 会使用:

1
/var/run/polarion/pg.pid

这个 PID 文件位于容器自己的可写层,不在外置运行目录里。

之前容器退出后,容器层仍然保留了旧 PID;下一次执行 docker start 时,脚本看到 PID 文件就直接走 status

但这个 PID 已经不对应当前容器中的 PostgreSQL,于是启动脚本以退出码 1 结束,Apache 也不会继续启动。

即使把 stale PID 清掉,三个副本仍然不能并行运行,因为它们会竞争:

  • 同一个宿主机 HTTP 端口 25080
  • 同一个宿主机 PostgreSQL 端口 25433
  • 同一个 data/postgres-data
  • 同一个 polarion.properties 和 SVN 数据。

因此,正确的修复不是反复点击三个容器的 Start,而是修复入口脚本,并只重建一个依赖容器。

只保留一个依赖容器

现在使用独立仓库维护脚本:

Polarion_Docker_Development_Environment

仓库中的 polarion2506/polarion2506-parallel.sh 虽然保留了 parallel 这个历史名称,但它只管理一个 2506 依赖容器 polarion2506-services

这里的 parallel 指它可以和已有的 Polarion 22R1 容器共存,不是指创建多个 2506 副本。

清理旧副本时,只删除容器对象,不删除外置数据:

1
2
3
docker rm \
  polarion2506-services-recovery \
  polarion2506-services-recovery-before-t4-20260807

不要加 -v,也不要删除:

1
/Volumes/Data/Polarion/Polarion2506-runtime

最终保留:

1
polarion2506-services

重建镜像和运行目录的区别

重建镜像

镜像中已经加入 stale PID 的安全处理:启动 PostgreSQL 前会检查 /var/run/polarion/pg.pid,只有当 PID 无效、对应进程不是 PostgreSQL,或不是当前 data/postgres-data 时才删除它。

Dockerfile 也显式安装了 procps,供进程检查使用。

在仓库目录中构建:

1
2
3
4
5
cd Polarion_Docker_Development_Environment/polarion2506
cp env.example .env.local
# 修改 .env.local 中的安装包、运行目录和 Node 路径
source .env.local
./build-image.sh

脚本使用 Docker BuildKit named context 读取外部安装包。安装包不会复制到 Git 仓库中;默认文件名是:

1
PolarionALM_2506.2512_linux.zip

如果客户包文件名不同,可以在 .env.local 修改 POLARION2506_PACKAGE_NAME

重建镜像不会删除、覆盖或自动还原外置运行目录。它只更新 polarion:2506-installer 镜像。

重新提取运行时

如果需要在一个新的空目录安装 Polarion 2506:

1
./install-runtime.sh

它把安装结果写入 POLARION2506_RUNTIME,但不会启动常驻依赖服务。脚本会拒绝覆盖一个非空且不是 Polarion 2506 的目录;不要为了修复 stale PID 删除整个 data 目录。

重建唯一依赖容器

镜像重建后,停止的旧容器仍可能使用旧的 entrypoint。日常启动脚本会自动处理这种情况:

1
./polarion2506-parallel.sh start

它的行为是:

  • polarion2506-services 已运行:只显示状态,不重复创建;
  • 容器已停止:删除旧容器层并重新创建;
  • 只执行 docker rm,不执行 docker rm -v
  • 外置的 Polarion、SVN 和 PostgreSQL 数据仍然保留。

如果需要明确强制重建正在运行的依赖容器:

1
./polarion2506-parallel.sh restart

macOS ARM 修复

2506 安装包中的图表和公式渲染器带有 Linux x86_64 Node。宿主机是 Apple Silicon 时,Eclipse/PDE 启动 Java 后会执行这个文件,典型错误是:

1
2
cannot execute binary file
exit code 126

容器是 Linux,Eclipse 是 macOS 宿主机进程,因此不能在 Linux Dockerfile 中写入 macOS Node。

运行时提取到外置磁盘后,只替换插件目录中的 node/bin/node,保留 Polarion 自己的 JS 文件和 node_modules

1
2
./polarion2506-arm-node.sh apply
./polarion2506-arm-node.sh verify

脚本会先把原始文件备份为:

1
node.polarion-x86_64-original

POLARION_NODE_SOURCE 必须是 macOS arm64 的 Node 18.x。Intel Mac 或 Linux 主机不要执行这个 macOS 宿主机替换步骤。详细背景见《Polarion-Arm-环境修复》

日常使用

启动依赖服务

1
2
3
4
cd Polarion_Docker_Development_Environment/polarion2506
source .env.local
./polarion2506-parallel.sh start
./polarion2506-parallel.sh verify

默认端口:

服务 端口 说明
Apache HTTP 25080 容器提供的访问入口
PostgreSQL 25433 宿主机访问容器内 5433
Eclipse/PDE AJP 25089 2506 Java 进程监听
Eclipse/PDE control 25087 2506 Java control 端口
notification 40608 2506 Java 通知端口

启动 Java 应用

依赖容器正常后,再在 Eclipse 中启动外置运行目录里的 Polarion2506.launch

当前方案仍然由 Eclipse/PDE 启动 Java,这样可以继续使用 target platform、插件开发和断点调试;容器不会自动执行 Polarion Java。

如果 Eclipse 提示“工作空间已经被占用”,先不要删除锁文件。通常是之前的 Eclipse/PDE launch 还在运行,正在持有:

1
/Volumes/Data/Polarion/Polarion2506-runtime/data/workspace/.metadata/.lock

先查实际持有者:

1
2
lsof /Volumes/Data/Polarion/Polarion2506-runtime/data/workspace/.metadata/.lock
ps auxww | rg 'com\.polarion\.core\.boot\.app|Polarion2506-runtime'

如果能看到 Java PID,说明 Polarion 已经启动,直接使用当前实例,或在 Eclipse 的 Debug/Console 视图中点击 Terminate 后再启动。只有确认 Java 已退出、lsof 没有输出后,才能清理残留锁:

本次现场通过 lsof 确认,锁文件由宿主机 Java PID 77314 持有。该进程命令行包含 -Declipse.pde.launch=true-application com.polarion.core.boot.app 和 2506 runtime 的 -data 工作区。

因此这不是容器自动启动导致的重复 Java,而是之前的 Eclipse/PDE 实例仍在运行。此时直接访问 http://localhost:25080/polarion/ 即可;本次验证返回 HTTP 200。

1
2
3
4
rm -f \
  /Volumes/Data/Polarion/Polarion2506-runtime/data/workspace/.metadata/.lock \
  /Volumes/Data/Polarion/Polarion2506-runtime/data/workspace/.metadata/server.pid \
  /Volumes/Data/Polarion/Polarion2506-runtime/data/workspace/polarion-data/cache/.lock

截图中在 Docker 容器里执行 /opt/polarion/bin/polarion.init stop,不会停止宿主机 Eclipse 启动的 Java;当前 host/Eclipse 模式不需要使用这个命令。

停止服务

1
./polarion2506-parallel.sh stop

只停止容器,不删除容器对象。下一次执行 start 时,如果容器处于停止状态,脚本会重建容器层,以避免再次复用 stale PID。

查看状态和日志:

1
2
./polarion2506-parallel.sh status
docker logs --tail 200 polarion2506-services

在其他电脑复用

其他电脑只需要重新准备本机路径,不需要把 Polarion 安装包提交到仓库:

1
2
3
4
5
6
7
8
9
git clone https://github.com/2han9wen71an/Polarion_Docker_Development_Environment.git
cd Polarion_Docker_Development_Environment/polarion2506
cp env.example .env.local
# 修改 POLARION_PACKAGE_ROOT、POLARION2506_RUNTIME、端口和 Node 路径
source .env.local
./build-image.sh
./install-runtime.sh
./polarion2506-arm-node.sh apply       # 仅 macOS arm64
./polarion2506-parallel.sh start

.env.local、安装 ZIP、运行目录和 Node 二进制已经在 .gitignore 中排除。

每台电脑可以使用不同的外置磁盘路径和端口,但同一台电脑上同一个运行目录只应绑定一个 polarion2506-services

总结

这次故障的关键点有三个:

  1. 三个容器其实共享同一个 Polarion 2506 运行目录和端口,不应该并行创建。
  2. stale /var/run/polarion/pg.pid 属于旧容器层;修复入口脚本后必须重建容器,不能只反复 docker start
  3. Docker 重建、外置运行目录、macOS ARM Node 修复和 Eclipse Java 启动是四个独立步骤。

以后只需要记住这一条主线:

1
2
3
4
5
build-image.sh(需要时)
    → install-runtime.sh(新目录时)
    → polarion2506-arm-node.sh apply(macOS ARM 首次)
    → polarion2506-parallel.sh start
    → Eclipse 启动 Polarion2506.launch
坚持原创技术分享,您的支持将鼓励我继续创作!