Apache Tez 0.10.5 Docker Compose 部署指南

使用 Docker Compose 一键编排 Apache Tez 0.10.5 与 Hadoop 3.4.1 单机环境,含 namenode、datanode、yarn、tez-client 五服务栈,附编排文件、持久化与运维排障。

Apache TezApache Tez2026/10/12

Apache Tez 0.10.5 Docker Compose 部署指南

一、环境信息

项目值
宿主机操作系统Ubuntu 22.04(CentOS 8 步骤一致)
Docker29.8.0
Docker Composev5.5.1(docker compose v2 插件)
Hadoop 镜像apache/hadoop:3.4.1
Tez0.10.5(apache-tez-0.10.5-bin.tar.gz)
编排目录/work/tez-compose
服务拓扑namenode、datanode、resourcemanager、nodemanager、tez-client 共 5 个服务

本文实测环境:在 Docker 29.8.0 + Compose v5.5.1 上完成镜像构建与整套编排,OrderedWordCount 作业在容器栈内运行成功(DAG: State: SUCCEEDED),以下文件与回显均为实测记录。

二、镜像选型说明

  • Hadoop 基础镜像:选用官方 apache/hadoop:3.4.1。该镜像内置 /opt/starter.sh 与 /opt/envtoconf.py,支持通过环境变量(形如 CORE-SITE.XML_fs.defaultFS)直接注入配置文件属性,无需手工改写 XML,是与 Tez 0.10.5 构建基线一致的版本。
  • Tez 镜像:Apache 不提供官方 Tez 镜像。方案是基于 apache/hadoop:3.4.1 构建 tez-client 镜像:把 apache-tez-0.10.5-bin.tar.gz 解压进 /opt/tez,并预置作业脚本。
  • 版本对应关系:Tez 0.10.5 发行包内捆绑 Hadoop 3.4.1 客户端库,镜像内 Hadoop 也用 3.4.1,避免 shim 探测与类冲突问题。
  • 镜像内默认用户为 hadoop(uid 1000),JRE 位于 /usr/lib/jvm/jre。

三、前置条件

宿主机已安装 Docker 与 compose 插件,并确认版本:

docker version --format 'Docker {{.Server.Version}}'

回显:

Docker 29.8.0
docker compose version

回显:

Docker Compose version v5.5.1

拉取 Hadoop 官方镜像:

docker pull apache/hadoop:3.4.1

回显(节选):

3.4.1: Pulling from apache/hadoop
Digest: sha256:69ffa97339af0e35e4da02f9a3b4df2d9e0b3f5d0c1e0f4dd7f29cbcc7ad6f76
Status: Downloaded newer image for apache/hadoop:3.4.1

下载 Tez 二进制包到编排目录:

mkdir -p /work/tez-compose && cd /work/tez-compose
wget https://downloads.apache.org/tez/0.10.5/apache-tez-0.10.5-bin.tar.gz -O apache-tez-0.10.5-bin.tar.gz

回显(节选):

apache-tez-0.10.5-bin.tar.gz   100%[===================>]  90.11M  10.7MB/s  in 9.2s

如果宿主机无法直连 Docker Hub,可先在能联网的机器上执行 docker pull 与 docker save,再在目标机执行 docker load 导入(实测导入回显):

Loaded image: apache/hadoop:3.4.1

四、部署步骤

4.1 编写 Dockerfile.tez

cat > /work/tez-compose/Dockerfile.tez <<'EOF'
FROM apache/hadoop:3.4.1
USER root
RUN mkdir -p /opt/tez /opt/tez-jobs
COPY apache-tez-0.10.5-bin.tar.gz /tmp/
RUN tar -xzf /tmp/apache-tez-0.10.5-bin.tar.gz -C /opt/tez --strip-components=1 && rm -f /tmp/apache-tez-0.10.5-bin.tar.gz
COPY run-job.sh /opt/tez-jobs/run-job.sh
RUN chmod +x /opt/tez-jobs/run-job.sh
USER hadoop
EOF

4.2 编写作业脚本 run-job.sh

该脚本在 tez-client 容器内执行:等待 HDFS 退出安全模式、等待 NodeManager 注册,然后上传 Tez 运行时包、灌入测试数据、提交 OrderedWordCount 并打印结果:

cat > /work/tez-compose/run-job.sh <<'EOF'
#!/usr/bin/env bash
set -e

export TEZ_HOME=/opt/tez
export TEZ_CONF_DIR=$HADOOP_CONF_DIR
export HADOOP_CLASSPATH=$TEZ_CONF_DIR:$TEZ_HOME/*:$TEZ_HOME/lib/*

echo "== waiting for HDFS =="
until hdfs dfsadmin -safemode get 2>/dev/null | grep -q OFF; do sleep 3; done
echo "HDFS ready"

echo "== waiting for YARN node =="
until yarn node -list 2>/dev/null | grep -qE "RUNNING"; do sleep 3; done
echo "YARN ready"

hdfs dfs -mkdir -p /apps/tez-0.10.5
hdfs dfs -put -f $TEZ_HOME/share/tez.tar.gz /apps/tez-0.10.5/
echo "tez.tar.gz uploaded to HDFS"

hdfs dfs -mkdir -p /data/wc/input
printf "hello tez\nhello hadoop\napache tez is fast\nteza tez hello\n" > /tmp/wc.txt
hdfs dfs -put -f /tmp/wc.txt /data/wc/input/wc.txt

echo "== running OrderedWordCount =="
hadoop jar $TEZ_HOME/tez-examples-0.10.5.jar orderedwordcount /data/wc/input/wc.txt /data/wc/output

echo "== word counts =="
hdfs dfs -cat /data/wc/output/*
echo "== done =="
EOF

4.3 编写 compose.yaml

cat > /work/tez-compose/compose.yaml <<'EOF'
services:
  namenode:
    image: apache/hadoop:3.4.1
    hostname: namenode
    environment:
      CORE-SITE.XML_fs.defaultFS: hdfs://namenode:9000
      HDFS-SITE.XML_dfs.namenode.name.dir: /data/hadoop/namenode
    ports:
      - "9870:9870"
      - "8088:8088"
    volumes:
      - nn_data:/data/hadoop
    healthcheck:
      test: ["CMD-SHELL", "hdfs dfsadmin -safemode get 2>/dev/null | grep -q OFF"]
      interval: 10s
      timeout: 5s
      retries: 30
    command: bash -c "sudo mkdir -p /data/hadoop/namenode && sudo chown -R hadoop:users /data/hadoop && if [ ! -d /data/hadoop/namenode/current ]; then hdfs namenode -format -force; fi && exec hdfs namenode"

  datanode:
    image: apache/hadoop:3.4.1
    hostname: datanode
    environment:
      CORE-SITE.XML_fs.defaultFS: hdfs://namenode:9000
      HDFS-SITE.XML_dfs.datanode.data.dir: /data/hadoop-dn/datanode
    depends_on:
      namenode:
        condition: service_healthy
    volumes:
      - dn_data:/data/hadoop-dn
    command: bash -c "sudo mkdir -p /data/hadoop-dn/datanode && sudo chown -R hadoop:users /data/hadoop-dn && exec hdfs datanode"

  resourcemanager:
    image: apache/hadoop:3.4.1
    hostname: resourcemanager
    environment:
      CORE-SITE.XML_fs.defaultFS: hdfs://namenode:9000
      YARN-SITE.XML_yarn.resourcemanager.hostname: resourcemanager
      YARN-SITE.XML_yarn.nodemanager.aux-services: mapreduce_shuffle
    depends_on:
      namenode:
        condition: service_healthy
    command: yarn resourcemanager

  nodemanager:
    image: apache/hadoop:3.4.1
    hostname: nodemanager
    environment:
      CORE-SITE.XML_fs.defaultFS: hdfs://namenode:9000
      YARN-SITE.XML_yarn.resourcemanager.hostname: resourcemanager
      YARN-SITE.XML_yarn.nodemanager.aux-services: mapreduce_shuffle
      YARN-SITE.XML_yarn.nodemanager.resource.memory-mb: "4096"
      YARN-SITE.XML_yarn.nodemanager.resource.cpu-vcores: "4"
      YARN-SITE.XML_yarn.nodemanager.vmem-check-enabled: "false"
    depends_on:
      - resourcemanager
    command: yarn nodemanager

  tez-client:
    build:
      context: .
      dockerfile: Dockerfile.tez
    image: tez-client:0.10.5
    hostname: tez-client
    environment:
      CORE-SITE.XML_fs.defaultFS: hdfs://namenode:9000
      YARN-SITE.XML_yarn.resourcemanager.hostname: resourcemanager
      TEZ-SITE.XML_tez.lib.uris: hdfs:///apps/tez-0.10.5/tez.tar.gz
      TEZ-SITE.XML_tez.use.cluster.hadoop-libs: "false"
      TEZ-SITE.XML_tez.am.resource.memory.mb: "1024"
      TEZ-SITE.XML_tez.am.launch.cmd-opts: -Xmx512m
      TEZ-SITE.XML_tez.task.resource.memory.mb: "1024"
      TEZ-SITE.XML_tez.task.launch.cmd-opts: -Xmx512m
    depends_on:
      namenode:
        condition: service_healthy
      nodemanager:
        condition: service_started
    command: bash /opt/tez-jobs/run-job.sh

volumes:
  nn_data:
  dn_data:
EOF

关键设计说明:

  • 配置注入:apache/hadoop 镜像的 entrypoint 会先执行 /opt/envtoconf.py,把 CORE-SITE.XML_、HDFS-SITE.XML_、YARN-SITE.XML_、TEZ-SITE.XML_ 前缀的环境变量写入对应 XML(下划线后首个点前是属性名)。因此 tez.lib.uris 等参数无需挂载配置文件即可下发。
  • namenode 的 command 先用 sudo 修正 volume 属主(镜像内 hadoop 用户 uid 1000),再按需格式化,最后 exec hdfs namenode 常驻。不要使用镜像自带的 ENSURE_NAMENODE_DIR 变量做初始化:它在 command 之前执行,volume 属主还是 root,format 会因 Cannot create directory 失败。
  • 健康检查用 hdfs dfsadmin -safemode get 判定安全模式退出;datanode、resourcemanager、tez-client 都通过 depends_on 条件串行拉起。
  • namenode 与 datanode 分开挂两个命名卷,避免同一卷被两个服务同时挂载产生路径覆盖。
  • Tez AM 与 Task 的 JVM 堆通过 TEZ-SITE.XML_tez.am.launch.cmd-opts / tez.task.launch.cmd-opts 限定为 -Xmx512m,对应容器内存 1024 MB。

4.4 构建镜像并启动

cd /work/tez-compose && docker compose build

回显(节选):

#12 exporting layers
#12 writing image sha256:1d9c8b2f4a5e done
#13 DONE 5.9s
 Image tez-client:0.10.5 Built
cd /work/tez-compose && docker compose up -d

回显(节选):

 Container tez-compose-namenode-1 Started
 Container tez-compose-namenode-1 Healthy
 Container tez-compose-datanode-1 Started
 Container tez-compose-resourcemanager-1 Started
 Container tez-compose-nodemanager-1 Started
 Container tez-compose-tez-client-1 Started
cd /work/tez-compose && docker compose ps

回显:

NAME                            IMAGE                 STATUS
tez-compose-datanode-1          apache/hadoop:3.4.1   Up About a minute
tez-compose-namenode-1          apache/hadoop:3.4.1   Up About a minute (healthy)
tez-compose-nodemanager-1       apache/hadoop:3.4.1   Up About a minute
tez-compose-resourcemanager-1   apache/hadoop:3.4.1   Up About a minute

4.5 查看作业执行结果

tez-client 运行 run-job.sh 后自动退出,通过日志查看全过程:

docker compose logs tez-client --no-log-prefix

回显(节选):

== waiting for HDFS ==
HDFS ready
== waiting for YARN node ==
YARN ready
== running OrderedWordCount ==
2026-10-12 01:28:03 INFO DAGClientImpl: DAG: State: SUCCEEDED Progress: 100% TotalTasks: 3 Succeeded: 3 Running: 0 Failed: 0 Killed: 0
2026-10-12 01:28:03 INFO DAGClientImpl: DAG completed. FinalState=SUCCEEDED
== word counts ==
apache  1
fast    1
hadoop  1
is      1
teza    1
hello   3
tez     3
== done ==

在 resourcemanager 容器内确认应用状态:

docker exec tez-compose-resourcemanager-1 yarn application -list -appStates FINISHED

回显:

Total number of applications (application-types: [], states: [FINISHED] and tags: []):1
                Application-Id      Application-Name        Application-Type          User           Queue                   State             Final-State             Progress                        Tracking-URL
application_1791768456414_0001      OrderedWordCount                     TEZ        hadoop      root.default              FINISHED               SUCCEEDED                 100%                                 N/A

浏览器可访问 NameNode UI(http://宿主机IP:9870)与 YARN UI(http://宿主机IP:8088)查看集群与作业。

五、数据持久化说明

卷挂载点内容
nn_data/data/hadoop(namenode 容器)NameNode 元数据(/data/hadoop/namenode/current)
dn_data/data/hadoop-dn(datanode 容器)DataNode 数据块(/data/hadoop-dn/datanode)
  • 两个卷均由 Docker 管理(匿名卷在 compose.yaml 中命名为 nn_data/dn_data),docker compose down 不会删除数据;docker compose down -v 会连同卷一起删除,需谨慎。
  • 重启后 namenode 容器检测到 /data/hadoop/namenode/current 已存在会跳过格式化,直接加载元数据,HDFS 数据与 /apps/tez-0.10.5/tez.tar.gz、作业输入输出全部保留。
  • 若需要把数据落到宿主机指定目录,把 volumes 条目改为 ./data/namenode:/data/hadoop 与 ./data/datanode:/data/hadoop-dn 即可,属主修正逻辑已由启动命令覆盖。

六、常用环境变量表

环境变量示例值说明
CORE-SITE.XML_fs.defaultFShdfs://namenode:9000HDFS 入口地址
HDFS-SITE.XML_dfs.namenode.name.dir/data/hadoop/namenodeNameNode 元数据目录(必须与卷挂载一致)
HDFS-SITE.XML_dfs.datanode.data.dir/data/hadoop-dn/datanodeDataNode 数据目录
YARN-SITE.XML_yarn.resourcemanager.hostnameresourcemanagerRM 地址;nodemanager 与客户端必须设置,否则连 0.0.0.0:8031
YARN-SITE.XML_yarn.nodemanager.aux-servicesmapreduce_shuffleShuffle 服务,Tez 作业必需
YARN-SITE.XML_yarn.nodemanager.resource.memory-mb4096节点可分配内存
YARN-SITE.XML_yarn.nodemanager.vmem-check-enabledfalse关闭虚拟内存检查
TEZ-SITE.XML_tez.lib.urishdfs:///apps/tez-0.10.5/tez.tar.gzTez 运行时包位置
TEZ-SITE.XML_tez.am.resource.memory.mb1024Tez AM 容器内存
TEZ-SITE.XML_tez.am.launch.cmd-opts-Xmx512mTez AM 的 JVM 堆
TEZ-SITE.XML_tez.task.resource.memory.mb1024Tez Task 容器内存
TEZ-SITE.XML_tez.task.launch.cmd-opts-Xmx512mTez Task 的 JVM 堆

命名规则:文件名.XML_属性名,文件名中的点由下划线代替(core-site 写作 CORE-SITE)。该机制由镜像内 /opt/envtoconf.py 实现,支持任意 XML 属性注入。

七、常用配置参数说明

  • tez.lib.uris:指向 HDFS 上的 tez.tar.gz(由 run-job.sh 首次执行时上传)。变更 Tez 版本时同步修改该路径与上传文件。
  • tez.am.launch.cmd-opts 与 tez.task.launch.cmd-opts:JVM 堆上限,本方案固定 512 MB;调整时保持与对应 resource.memory.mb 约 1:2 的比例,避免容器超限被杀。
  • tez.use.cluster.hadoop-libs:保持 false,使用 Tez 包内自带的 Hadoop 3.4.1 库,与基础镜像版本一致。
  • yarn.nodemanager.resource.memory-mb:决定整套栈内能同时容纳的 Tez 容器数;4096 MB 时最多容纳约 3 个 1024 MB 容器(1 AM + 2 Task)。
  • HDFS 副本数:镜像默认单副本场景下无需配置;多 DataNode 部署时通过 HDFS-SITE.XML_dfs.replication 调整。

八、配置文件持久化

envtoconf 注入适合无状态参数;若需要携带完整 tez-site.xml 文件(如从已有集群迁移配置),用挂载方式替换 tez-client 内的配置目录:

  1. 在编排目录准备 conf/tez-site.xml(内容与本文示例一致)。
  2. 在 compose.yaml 的 tez-client 服务追加:
    volumes:
      - ./conf/tez-site.xml:/opt/tez/conf/tez-site.xml:ro
  1. 在 run-job.sh 中把 TEZ_CONF_DIR 指向挂载目录:
    environment:
      TEZ_CONF_DIR: /opt/tez/conf

注意挂载文件属主为 root 而容器内用户是 hadoop(uid 1000),只读挂载(:ro)即可正常读取。Hadoop 侧配置同理,可用 ./conf/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro 覆盖,但与 envtoconf 注入二选一,避免互相覆盖造成困惑。

九、等价 docker run 运行方式

不使用 Compose 时,按同样拓扑逐个启动(先创建网络与卷,命令按顺序单独执行):

docker network create teznet
docker volume create nn_data
docker volume create dn_data
docker run -d --name namenode --hostname namenode --network teznet -p 9870:9870 -p 8088:8088 -v nn_data:/data/hadoop -e CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -e HDFS-SITE.XML_dfs.namenode.name.dir=/data/hadoop/namenode apache/hadoop:3.4.1 bash -c "sudo mkdir -p /data/hadoop/namenode && sudo chown -R hadoop:users /data/hadoop && if [ ! -d /data/hadoop/namenode/current ]; then hdfs namenode -format -force; fi && exec hdfs namenode"
docker run -d --name datanode --hostname datanode --network teznet -v dn_data:/data/hadoop-dn -e CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -e HDFS-SITE.XML_dfs.datanode.data.dir=/data/hadoop-dn/datanode apache/hadoop:3.4.1 bash -c "sudo mkdir -p /data/hadoop-dn/datanode && sudo chown -R hadoop:users /data/hadoop-dn && exec hdfs datanode"
docker run -d --name resourcemanager --hostname resourcemanager --network teznet -e CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -e YARN-SITE.XML_yarn.resourcemanager.hostname=resourcemanager -e YARN-SITE.XML_yarn.nodemanager.aux-services=mapreduce_shuffle apache/hadoop:3.4.1 yarn resourcemanager
docker run -d --name nodemanager --hostname nodemanager --network teznet -e CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -e YARN-SITE.XML_yarn.resourcemanager.hostname=resourcemanager -e YARN-SITE.XML_yarn.nodemanager.aux-services=mapreduce_shuffle -e YARN-SITE.XML_yarn.nodemanager.resource.memory-mb=4096 apache/hadoop:3.4.1 yarn nodemanager

tez-client 建议通过 compose build 产出的 tez-client:0.10.5 镜像启动(等价依赖条件用外部脚本保证):

docker run -d --name tez-client --hostname tez-client --network teznet -e CORE-SITE.XML_fs.defaultFS=hdfs://namenode:9000 -e YARN-SITE.XML_yarn.resourcemanager.hostname=resourcemanager -e TEZ-SITE.XML_tez.lib.uris=hdfs:///apps/tez-0.10.5/tez.tar.gz tez-client:0.10.5 bash /opt/tez-jobs/run-job.sh

逐容器启动时没有 compose 的 depends_on 等待逻辑,需在 namenode 健康后(约 30 秒)再启动后续容器。

十、常用运维命令

docker compose ps

查看各服务状态(namenode 应显示 healthy)。

docker compose logs -f namenode

实时跟踪 NameNode 日志;排障时同样适用于 datanode、resourcemanager、nodemanager。

docker exec -it tez-compose-tez-client-1 bash

进入 tez-client 交互环境,可直接执行 hdfs dfs、yarn application、hadoop jar 等命令(注意 TEZ_HOME=/opt/tez):

docker exec tez-compose-tez-client-1 hdfs dfs -cat /data/wc/output/*

回显:

apache  1
fast    1
hadoop  1
is      1
teza    1
hello   3
tez     3
docker stats

查看各容器 CPU 与内存占用。

docker compose restart nodemanager

单独重启某个服务。

docker compose down

停止并删除容器(保留数据卷)。

docker compose down -v

停止并删除容器与数据卷(NameNode 元数据与 HDFS 数据将全部清空)。

十一、常见问题

Q1:namenode 容器反复退出,日志报 Directory /data/hadoop/namenode is in an inconsistent state? A:volume 挂载点属主为 root,镜像内 hadoop 用户无法写入。确认 command 中包含 sudo chown -R hadoop:users /data/hadoop;并避免使用镜像自带的 ENSURE_NAMENODE_DIR 初始化(它执行在 command 之前,属主尚未修正)。

Q2:NameNode 启动即报 storage directory does not exist,指向 /tmp/hadoop-hadoop/dfs/name? A:镜像默认 dfs.namenode.name.dir 在 /tmp 下。必须在 namenode 服务中注入 HDFS-SITE.XML_dfs.namenode.name.dir=/data/hadoop/namenode 并挂载持久卷。

Q3:nodemanager 日志持续重试连接 0.0.0.0:8031,报 Your endpoint configuration is wrong? A:该容器缺少 yarn.resourcemanager.hostname。给 nodemanager 与 tez-client 都加上 YARN-SITE.XML_yarn.resourcemanager.hostname=resourcemanager。

Q4:tez-client 日志长时间停留在 waiting for YARN node? A:NodeManager 尚未注册成功。先 docker compose logs nodemanager 确认 NodeManager 正常连接 RM;常见根因是 Q3 或 RM 未启动完成,等待或修复后 tez-client 内的等待循环会自动继续。

Q5:作业失败,日志显示 Container 超内存被杀? A:将 TEZ-SITE.XML_tez.task.resource.memory.mb 从 1024 提高到 2048(保持 tez.task.launch.cmd-opts=-Xmx512m),为 JVM 堆外开销留足余量;或下调堆。

Q6:镜像构建或拉取时网络不通? A:在可联网环境执行 docker pull apache/hadoop:3.4.1 与 docker save -o hadoop341.tar apache/hadoop:3.4.1,拷贝到目标机后执行 docker load -i hadoop341.tar;Tez 包则用 downloads.apache.org 或镜像站下载 apache-tez-0.10.5-bin.tar.gz 放入构建上下文。

Q7:如何彻底重置整套环境? A:依次执行 docker compose down -v、删除构建缓存 docker rmi tez-client:0.10.5,再 docker compose build && docker compose up -d 重建。

十二、参考链接