Dockerfile 一键构建 Hadoop 镜像

读完这篇,你会用 Dockerfile + 外部配置文件的方式,从零构建一个 Hadoop 3.3.6 镜像。

所有 XML 和启动脚本都放在宿主机目录里,修改方便,排错清晰。

一、为什么要把配置文件放在外面?

之前我们把四个 XML 和 entrypoint.sh 全写在 Dockerfile 里,虽然能跑,但修改配置每次都要重新编辑 Dockerfile,维护起来不够直观。

把配置文件独立出来,目录结构清晰,将来换集群、改参数,只需动一两个文件,不用再碰 Dockerfile 主体。

二、最终目录结构

在你的 Mac 上创建一个新文件夹,比如 hadoop-docker,里面放这 6 个文件:

Plain 复制代码
hadoop-docker/
├── Dockerfile
├── core-site.xml
├── hdfs-site.xml
├── yarn-site.xml
├── mapred-site.xml
└── entrypoint.sh

三、逐个文件内容(直接复制粘贴)

1. Dockerfile

Dockerfile 复制代码
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive

# 安装必要软件
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget curl sudo openssh-server openssh-client openjdk-11-jdk net-tools vim \
    && rm -rf /var/lib/apt/lists/*

# 创建 hadoop 用户并授予 sudo 权限
RUN useradd -m hadoop -s /bin/bash && \
    echo "hadoop:hadoop" | chpasswd && \
    echo "hadoop ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER hadoop
WORKDIR /home/hadoop

# 配置 SSH 免密登录
RUN ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa && \
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys && \
    chmod 600 ~/.ssh/authorized_keys

# 下载并解压 Hadoop
RUN wget -q https://dlcdn.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz && \
    tar -xzf hadoop-3.3.6.tar.gz && mv hadoop-3.3.6 hadoop && rm hadoop-3.3.6.tar.gz

# 创建 Hadoop 所需目录
RUN mkdir -p /home/hadoop/hdfs/namenode /home/hadoop/hdfs/datanode /home/hadoop/hadoop/logs

# 拷贝外部配置文件(从构建上下文目录复制进镜像)
COPY core-site.xml /home/hadoop/hadoop/etc/hadoop/
COPY hdfs-site.xml /home/hadoop/hadoop/etc/hadoop/
COPY yarn-site.xml /home/hadoop/hadoop/etc/hadoop/
COPY mapred-site.xml /home/hadoop/hadoop/etc/hadoop/

# 将环境变量写入系统级配置,确保任何登录方式都能加载
# 将环境变量文件拷贝到系统目录,所有用户登录时自动加载
COPY hadoop-profile.sh /etc/profile.d/hadoop.sh

# 硬写入 JAVA_HOME 到 hadoop-env.sh,避免 SSH 启动时找不到
RUN sudo sed -i 's|# export JAVA_HOME=.*|export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-arm64|' /home/hadoop/hadoop/etc/hadoop/hadoop-env.sh

# 提前格式化 NameNode
RUN /home/hadoop/hadoop/bin/hdfs namenode -format -force

# 拷贝启动脚本
COPY entrypoint.sh /home/hadoop/entrypoint.sh
RUN sudo chmod +x /home/hadoop/entrypoint.sh

EXPOSE 9870 9000 9864 8088 8032 22
ENTRYPOINT ["/home/hadoop/entrypoint.sh"]

这个四个配置文件:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml 跟这篇【用 Docker 装 Hadoop,看这篇就够了】的一样,不再啰嗦

2. entrypoint.sh

Bash 复制代码
#!/bin/bash
sudo service ssh start
sudo -u hadoop bash -c "source /etc/profile.d/hadoop.sh && start-dfs.sh && start-yarn.sh"
tail -f /dev/null

所有文件粘贴好后,你的 hadoop-docker 目录就应该有这 6 个文件。

四、构建镜像

hadoop-docker 目录下打开终端,执行:

Bash 复制代码
docker build -t hadoop-single:v1 .
  • -t hadoop-single:v1:给镜像起名和打标签。
  • 最后的 . 表示构建上下文为当前目录,Docker 会从这里读取 Dockerfile 和配置文件。

构建过程大约需要几分钟。看到 Successfully tagged hadoop-single:v1 即为成功。

五、启动容器

Bash 复制代码
docker run -d --name hadoop-prod \
    -p 9870:9870 \
    -p 8088:8088 \
    -p 9000:9000 \
    -p 2222:22 \
    hadoop-single:v1

参数解释:

  • -d:后台运行
  • --name hadoop-prod:容器名称
  • -p 宿主机端口:容器端口:映射关键端口,方便从 Mac 访问
    • 9870:HDFS NameNode Web UI
    • 8088:YARN ResourceManager Web UI
    • 9000:HDFS RPC 端口(Spark、Flink 等客户端读写用)
    • 2222:SSH 端口(避免和 Mac 自身的 22 端口冲突)

检查容器运行状态:

Bash 复制代码
docker ps

看到 hadoop-prod 状态为 Up 即正常。

六、验证 Hadoop 服务

1. 浏览器访问

打开 Mac 的浏览器,输入:

  • HDFS NameNode:http://localhost:9870
  • YARN ResourceManager:http://localhost:8088

如果页面正常显示,说明 Hadoop 启动成功。

2. 进入容器使用命令行

Bash 复制代码
docker exec -it hadoop-prod su - hadoop

因为我们在 /etc/profile.d/hadoop.sh 里写了环境变量,所以使用 su - 登录后,HADOOP_HOME 和 PATH 都已经自动生效,直接就能用命令:

Bash 复制代码
hdfs dfs -mkdir /test
echo "hello hadoop" | hdfs dfs -put - /test/hello.txt
hdfs dfs -cat /test/hello.txt

输出 hello hadoop 即表示 HDFS 读写正常。

七、环境变量为何再也不会丢?

  • 我们放弃了仅在 ~/.bashrc~/.profile 里设变量,而是把 export 写到了 /etc/profile.d/hadoop.sh
  • 这个目录下的脚本会被任何用户的登录 shellsu -、SSH 登录)自动加载,连非交互式 shell 也能读到。
  • 同时还修改了 hadoop-env.sh,显式指定 JAVA_HOME,即使通过 SSH 远程启动 Hadoop 脚本,也绝不会再报 JAVA_HOME is not set