Kettle 9.1 Docker Compose 部署指南

基于 Docker Compose 部署 Pentaho Data Integration 9.1:同镜像编排 Kitchen 作业与 Carte 服务,含 Dockerfile、编排全文、构建启动输出、status 接口验证与常见问题。

KettleKettleETLDockerDocker Compose2026/10/12

Kettle 9.1 Docker Compose 部署指南

目标:在一台装有 Docker 的 Linux 服务器上,使用 Docker Compose 一键部署 Pentaho Data Integration(Kettle,下称 PDI)9.1 社区版:用同一个自建镜像同时编排「Kitchen 一次性作业」与「Carte 常驻 Web 服务」两个服务,完成构建、启动、作业执行与接口验证的完整闭环。全文命令与回显已在 Linux x86_64(Docker 29.8.0 + Compose v5.5.1)实测通过。

一、方案说明

1.1 服务组成与端口

PDI 9.1 解压目录内含完整的命令行执行器与 Web 服务组件,本方案用同一份程序目录构建一个镜像,编排两个服务:

服务定位命令端口restart 策略
pdi-kitchen一次性作业执行器,跑完即退出./kitchen.sh -file=<作业.kjb> -level=Basic无no
pdi-carte常驻 Web 服务(内嵌 Jetty),提供 HTTP 管理接口./carte.sh 0.0.0.0 80818081 对外映射unless-stopped

1.2 实测环境版本

项目版本
PDI9.1.0.0-324(build date 2020-09-07)
基础镜像eclipse-temurin:8-jre-jammy(JDK 8,见第八节 8.1 的 JDK 版本要求)
Docker29.8.0
Docker Composev5.5.1(插件版 docker compose)

二、前置条件

2.1 安装 Docker Engine

服务器需已安装 Docker Engine(19.03+,含 buildkit)。CentOS 8 参考安装:

dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker

Ubuntu 22.04 参考安装:

apt-get update
apt-get install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker

💡 说明:若服务器已装有可用的 Docker Engine 与 Compose 插件,跳过本节即可。

2.2 版本验证

docker --version
docker compose version

实测输出:

Docker version 29.8.0, build 88096ef
Docker Compose version v5.5.1

三、准备 PDI 程序目录

3.1 获取 data-integration 目录

PDI 9.1 社区版发行包 pdi-ce-9.1.0.0-324.zip(约 1749 MB)解压后得到 data-integration 目录,这就是构建镜像的全部程序文件。历史官方下载地址:

wget https://sourceforge.net/projects/pentaho/files/Pentaho%209.1/client-tools/pdi-ce-9.1.0.0-324.zip
unzip -q pdi-ce-9.1.0.0-324.zip

⚠️ 注意(渠道变迁):Hitachi Vantara 已清空 SourceForge 上 pentaho 项目的文件区,上述历史直链可能返回 404。替代获取方式:从企业内部留存的安装包解压,或从可信的第三方 Docker Hub 镜像(内含完整 PDI 目录结构)中提取 data-integration 目录。安装包 SHA256(以本文实测包为准):0f3c031d6d0a2d6f7eedd918a4f3d44a02006d1c8ccca9b99f7ceded3bb07ad8。

3.2 程序目录内容确认

ls data-integration | head -12

实测输出(节选):

ADDITIONAL-FILES
Carte.bat
carte.sh
classes
Data Integration.app
Data Service JDBC Driver
docs
drivers
Encr.bat
encr.sh
import.sh
kitchen.bat
kitchen.sh

四、编写编排文件

4.1 项目目录结构

在服务器上规划项目目录 /opt/kettle-compose,结构如下:

/opt/kettle-compose/
├── Dockerfile
├── docker-compose.yml
├── jobs/                    # 作业与转换文件(只读挂入 pdi-kitchen)
│   ├── test_gen_log.ktr
│   └── test_gen_log_job.kjb
└── src/
    └── data-integration/    # 第三步解压得到的 PDI 程序目录
mkdir -p /opt/kettle-compose/jobs /opt/kettle-compose/src
cp -a data-integration /opt/kettle-compose/src/
cd /opt/kettle-compose

4.2 Dockerfile

FROM eclipse-temurin:8-jre-jammy
COPY src/data-integration /opt/pentaho/data-integration
ENV PENTAHO_DI_JAVA_OPTIONS="-Xms256m -Xmx512m"
WORKDIR /opt/pentaho/data-integration

要点说明:

  • 基础镜像必须为 JDK 8(eclipse-temurin:8-jre-jammy):PDI 9.1 启动脚本硬编码 -Djava.endorsed.dirs,JDK 11+ 直接拒绝启动(详见第八节 8.1)。
  • PENTAHO_DI_JAVA_OPTIONS 是 PDI 启动脚本读取的专用 JVM 变量,-Xms256m -Xmx512m 将堆限制在 256–512 MB。
  • WORKDIR 指向程序目录,compose 的 command 才能用 ./kitchen.sh 相对路径。

4.3 docker-compose.yml

services:
  pdi-kitchen:
    build: .
    container_name: pdi-kitchen
    command: ["./kitchen.sh", "-file=/opt/pentaho/jobs/test_gen_log_job.kjb", "-level=Basic"]
    volumes:
      - ./jobs:/opt/pentaho/jobs:ro
    restart: "no"
  pdi-carte:
    build: .
    container_name: pdi-carte
    command: ["./carte.sh", "0.0.0.0", "8081"]
    ports:
      - "8081:8081"
    restart: unless-stopped

要点说明:

  • pdi-kitchen 挂载宿主机 jobs/ 目录为只读,作业文件改动无需重建镜像,下次运行即生效。
  • pdi-carte 以命令行方式启动(接口地址 + 端口),默认监听账号为 cluster/cluster(详见第六节 6.3 与第八节 8.3)。
  • 两个服务 build: . 共用一个镜像,首次 up 时自动构建。

4.4 作业与转换文件

写入一个最小可验证的示例作业:START → 执行转换(生成 3 行数据写入日志)。先写转换文件 /opt/kettle-compose/jobs/test_gen_log.ktr:

<?xml version="1.0" encoding="UTF-8"?>
<transformation>
  <info>
    <name>gen_log_test</name>
    <trans_type>Normal</trans_type>
    <directory>/</directory>
    <size_rowset>10000</size_rowset>
    <created_user>-</created_user>
    <created_date>2026/10/12 12:00:00.000</created_date>
    <modified_user>-</modified_user>
    <modified_date>2026/10/12 12:00:00.000</modified_date>
  </info>
  <order>
    <hop><from>gen</from><to>log</to><enabled>Y</enabled></hop>
  </order>
  <notepads></notepads>
  <step>
    <name>gen</name>
    <type>RowGenerator</type>
    <distribute>Y</distribute>
    <copies>1</copies>
    <partitioning><method>none</method><schema_name/></partitioning>
    <fields>
      <field>
        <name>msg</name>
        <type>String</type>
        <nullif>hello-kettle</nullif>
        <length>-1</length>
        <precision>-1</precision>
        <set_empty_string>N</set_empty_string>
      </field>
    </fields>
    <limit>3</limit>
    <never_ending>N</never_ending>
    <cluster_schema/>
    <GUI><xloc>100</xloc><yloc>100</yloc><draw>Y</draw></GUI>
  </step>
  <step>
    <name>log</name>
    <type>WriteToLog</type>
    <distribute>Y</distribute>
    <copies>1</copies>
    <partitioning><method>none</method><schema_name/></partitioning>
    <log_level>log_level_basic</log_level>
    <displayHeader>Y</displayHeader>
    <limitRows>N</limitRows>
    <limitRowsNumber>0</limitRowsNumber>
    <logmessage>msg</logmessage>
    <byname>Y</byname>
    <cluster_schema/>
    <GUI><xloc>300</xloc><yloc>100</yloc><draw>Y</draw></GUI>
  </step>
  <step_error_handling></step_error_handling>
  <slave_transformation>N</slave_transformation>
  <attributes/>
</transformation>

再写作业文件 /opt/kettle-compose/jobs/test_gen_log_job.kjb(注意其中引用的转换路径必须是容器内挂载路径 /opt/pentaho/jobs/test_gen_log.ktr):

<?xml version="1.0" encoding="UTF-8"?>
<job>
  <name>run_ktr_job</name>
  <directory>/</directory>
  <created_user>-</created_user>
  <created_date>2026/10/12 12:00:00.000</created_date>
  <modified_user>-</modified_user>
  <modified_date>2026/10/12 12:00:00.000</modified_date>
  <parameters></parameters>
  <slaveservers></slaveservers>
  <entries>
    <entry>
      <name>START</name>
      <type>SPECIAL</type>
      <start>Y</start>
      <dummy>N</dummy>
      <repeat>N</repeat>
      <schedulerType>0</schedulerType>
      <intervalSeconds>60</intervalSeconds>
      <intervalMinutes>60</intervalMinutes>
      <hour>12</hour>
      <minutes>0</minutes>
      <weekDay>1</weekDay>
      <DayOfMonth>1</DayOfMonth>
      <parallel>N</parallel>
      <draw>Y</draw>
      <nr>0</nr>
      <xloc>100</xloc>
      <yloc>100</yloc>
    </entry>
    <entry>
      <name>run trans</name>
      <type>TRANS</type>
      <filename>/opt/pentaho/jobs/test_gen_log.ktr</filename>
      <arg_from_previous>N</arg_from_previous>
      <exec_local>Y</exec_local>
      <exec_remote>N</exec_remote>
      <clear_rows>N</clear_rows>
      <wait_until_finished>Y</wait_until_finished>
      <parameters><pass_all_parameters>Y</pass_all_parameters></parameters>
      <parallel>N</parallel>
      <draw>Y</draw>
      <nr>0</nr>
      <xloc>300</xloc>
      <yloc>100</yloc>
    </entry>
  </entries>
  <hops>
    <hop>
      <from>START</from><to>run trans</to>
      <from_nr>0</from_nr><to_nr>0</to_nr><nr>0</nr>
      <enabled>Y</enabled><evaluation>Y</evaluation><unconditional>N</unconditional>
    </hop>
  </hops>
  <notepads></notepads>
</job>

五、构建与启动

5.1 构建镜像

cd /opt/kettle-compose
docker compose build

实测输出(尾部,首次构建约 1–2 分钟,COPY 1.8 GB 程序目录占大头):

#10 unpacking to docker.io/library/kettle-compose-pdi-carte:latest 11.1s done
#10 DONE 71.1s
#9 [pdi-kitchen] exporting to image
#9 unpacking to docker.io/library/kettle-compose-pdi-kitchen:latest 11.1s done
#9 DONE 71.1s
#11 [pdi-kitchen] resolving provenance for metadata file
#11 DONE 0.0s
#12 [pdi-carte] resolving provenance for metadata file
#12 DONE 0.0s
 Image kettle-compose-pdi-kitchen Built
 Image kettle-compose-pdi-carte Built

5.2 启动服务

docker compose up -d

实测输出:

 Network kettle-compose_default Creating
 Network kettle-compose_default Created
 Container pdi-kitchen Creating
 Container pdi-carte Creating
 Container pdi-kitchen Created
 Container pdi-carte Created
 Container pdi-carte Starting
 Container pdi-kitchen Starting
 Container pdi-carte Started
 Container pdi-kitchen Started

5.3 查看服务状态

docker compose ps

实测输出:

NAME          IMAGE                        COMMAND                  SERVICE       CREATED         STATUS         PORTS
pdi-carte     kettle-compose-pdi-carte     "/__cacert_entrypoin…"   pdi-carte     5 seconds ago   Up 3 seconds   0.0.0.0:8081->8081/tcp, [::]:8081->8081/tcp
pdi-kitchen   kettle-compose-pdi-kitchen   "/__cacert_entrypoin…"   pdi-kitchen   5 seconds ago   Up 3 seconds

pdi-kitchen 是一次性作业,执行完会自动退出。稍候约 1 分钟后再看完整状态:

docker compose ps -a

实测输出:

NAME          IMAGE                        COMMAND                  SERVICE       CREATED         STATUS         PORTS
pdi-carte     kettle-compose-pdi-carte     "/__cacert_entrypoin…"   pdi-carte     About a minute ago   Up About a minute   0.0.0.0:8081->8081/tcp, [::]:8081->8081/tcp
pdi-kitchen   kettle-compose-pdi-kitchen   "/__cacert_entrypoin…"   pdi-kitchen   About a minute ago   Exited (0) About a minute ago

Exited (0) 表示作业正常执行完毕退出。

六、运行验证

6.1 作业执行日志

docker logs pdi-kitchen

实测输出(尾部;开头的 Karaf/OSGI 初始化日志略):

14:31:29,019 INFO  [DriverManager] 0 drivers will be installed.
14:31:29,020 INFO  [DriverManager] Finished installing drivers kars.
2026/10/12 14:31:29 - run_ktr_job - Start of job execution
2026/10/12 14:31:29 - run_ktr_job - Job execution finished
2026/10/12 14:31:29 - Carte - Installing timer to purge stale objects after 1440 minutes.
2026/10/12 14:31:29 - Finished!
2026/10/12 14:31:29 - Start=2026/10/12 14:31:29.126, Stop=2026/10/12 14:31:29.175
2026/10/12 14:31:29 - Processing ended after 0 seconds.

Job execution finished + Finished! + Exited (0) 三者齐备,说明作业链路(kitchen → kjb → ktr)在镜像内完整跑通。

6.2 Carte 服务启动确认

docker logs pdi-carte 2>&1 | tail -3

实测输出:

14:31:31,839 INFO  [DriverManager] Finished installing drivers kars.
14:31:31 - Carte - Installing timer to purge stale objects after 1440 minutes.
14:31:32 - Carte - Created listener for webserver @ address : 0.0.0.0:8081

6.3 status 接口验证

在服务器本机访问映射出的 8081 端口:

curl -s -o /dev/null -w '%{http_code}\n' -u cluster:cluster http://localhost:8081/kettle/status/

实测输出:

200

⚠️ 注意(默认凭据):carte.sh 接口地址 端口 这种命令行方式启动的 Carte 使用内置默认账号 cluster/cluster,本文 docker-compose.yml 正是这种方式,因此验证用 cluster:cluster。若用配置文件方式启动(carte.sh <配置.xml>),账号密码以配置文件中的 username/password 为准。错误凭据返回 401。

七、日常运维

7.1 查看 Carte 实时日志

docker logs -f pdi-carte

按 Ctrl+C 退出跟踪(不影响服务)。

7.2 停止与清理

cd /opt/kettle-compose
docker compose down

实测输出:

 Container pdi-carte  Stopping
 Container pdi-kitchen Stopping
 Container pdi-kitchen Stopped
 Container pdi-kitchen Removing
 Container pdi-kitchen Removed
 Container pdi-carte Stopped
 Container pdi-carte Removing
 Container pdi-carte Removed
 Network kettle-compose_default Removing
 Network kettle-compose_default Removed

如需连镜像一并删除:

docker compose down --rmi local

7.3 更新作业文件

作业与转换文件通过 volumes 只读挂载,直接修改宿主机 /opt/kettle-compose/jobs/ 下的文件后重新运行作业即可,无需重建镜像:

docker compose run --rm pdi-kitchen

docker compose run 会按服务定义的 command 新起一个一次性实例执行作业,跑完自动清理。

7.4 程序目录变更后重建镜像

若替换了 src/data-integration(例如升级 PDI 版本),需要重新构建并滚动重启 Carte:

cd /opt/kettle-compose
docker compose build
docker compose up -d --force-recreate pdi-carte

八、常见问题

8.1 启动脚本与 JDK 11+ 不兼容

现象:容器启动即退出,日志中出现:

-Djava.endorsed.dirs=... is not supported. Endorsed standards and standalone APIs
in modular form will be supported via the concept of upgradeable modules.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

原因:PDI 9.1 启动脚本(kitchen/pan/carte/spoon 共用)固定拼接非空的 -Djava.endorsed.dirs,JDK 9+ 已移除该机制并直接拒绝启动。解决:基础镜像锁定 JDK 8(本文使用 eclipse-temurin:8-jre-jammy)。

8.2 宿主机 8081 端口被占用

现象:pdi-carte 反复重启,docker logs pdi-carte 尾部出现:

Caused by: java.net.BindException: Address already in use

排查占用并释放端口(或修改 docker-compose.yml 的端口映射为其他宿主机端口,如 "18081:8081"):

ss -lntp | grep 8081

8.3 status 接口返回 401

本文编排的 Carte 以命令行方式启动,默认账号为 cluster/cluster;用 admin:q1w2e3r4 等其他凭据访问会得到 401:

HTTP/1.1 401 Unauthorized

解决:使用 cluster:cluster 访问,或改用配置文件方式启动并自定义账号(在配置文件的 slaveserver 节点设置 username/password)。

8.4 内存控制

Dockerfile 中 PENTAHO_DI_JAVA_OPTIONS="-Xms256m -Xmx512m" 已将 JVM 堆限制在 256–512 MB。实测 Carte 常驻内存约 500 MB 上下。若服务器内存紧张,可将两值对齐为 -Xms256m -Xmx256m。

九、参考链接