Apache Tez 0.10.5 Docker Compose 部署指南
使用 Docker Compose 一键编排 Apache Tez 0.10.5 与 Hadoop 3.4.1 单机环境,含 namenode、datanode、yarn、tez-client 五服务栈,附编排文件、持久化与运维排障。
Apache Tez 0.10.5 Docker Compose 部署指南
一、环境信息
| 项目 | 值 |
|---|---|
| 宿主机操作系统 | Ubuntu 22.04(CentOS 8 步骤一致) |
| Docker | 29.8.0 |
| Docker Compose | v5.5.1(docker compose v2 插件) |
| Hadoop 镜像 | apache/hadoop:3.4.1 |
| Tez | 0.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.defaultFS | hdfs://namenode:9000 | HDFS 入口地址 |
| HDFS-SITE.XML_dfs.namenode.name.dir | /data/hadoop/namenode | NameNode 元数据目录(必须与卷挂载一致) |
| HDFS-SITE.XML_dfs.datanode.data.dir | /data/hadoop-dn/datanode | DataNode 数据目录 |
| YARN-SITE.XML_yarn.resourcemanager.hostname | resourcemanager | RM 地址;nodemanager 与客户端必须设置,否则连 0.0.0.0:8031 |
| YARN-SITE.XML_yarn.nodemanager.aux-services | mapreduce_shuffle | Shuffle 服务,Tez 作业必需 |
| YARN-SITE.XML_yarn.nodemanager.resource.memory-mb | 4096 | 节点可分配内存 |
| YARN-SITE.XML_yarn.nodemanager.vmem-check-enabled | false | 关闭虚拟内存检查 |
| TEZ-SITE.XML_tez.lib.uris | hdfs:///apps/tez-0.10.5/tez.tar.gz | Tez 运行时包位置 |
| TEZ-SITE.XML_tez.am.resource.memory.mb | 1024 | Tez AM 容器内存 |
| TEZ-SITE.XML_tez.am.launch.cmd-opts | -Xmx512m | Tez AM 的 JVM 堆 |
| TEZ-SITE.XML_tez.task.resource.memory.mb | 1024 | Tez Task 容器内存 |
| TEZ-SITE.XML_tez.task.launch.cmd-opts | -Xmx512m | Tez 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 内的配置目录:
- 在编排目录准备 conf/tez-site.xml(内容与本文示例一致)。
- 在 compose.yaml 的 tez-client 服务追加:
volumes:
- ./conf/tez-site.xml:/opt/tez/conf/tez-site.xml:ro
- 在 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 重建。
十二、参考链接
- apache/hadoop 官方镜像(Docker Hub):https://hub.docker.com/r/apache/hadoop
- Apache Tez 下载页:https://downloads.apache.org/tez/
- Tez 官方安装文档:https://tez.apache.org/install.html
- Docker Compose 文档:https://docs.docker.com/compose/
- YARN Resource Model(容器内存模型):https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-site/ResourceModel.html