6 Laboratorio: HDFS con Docker, desde la instalación hasta las réplicas
Serie Big Data · Wilder Ramírez Delgado
Construiremos un NameNode y tres DataNodes en una computadora. Cargaremos archivos, observaremos bloques y réplicas, consultaremos el portal y comprobaremos qué sucede al detener un nodo.
Duración orientativa: 90–120 minutos, más las descargas. Entorno principal: Windows con Ubuntu 24.04 en WSL2 y Docker Desktop, en un equipo x86-64. Como recomendación práctica para este laboratorio, disponer de 16 GB de RAM y 15 GB libres facilita trabajar con Windows, Docker y los cuatro contenedores. No es un requisito mínimo oficial de Hadoop.
Este es un notebook de laboratorio guiado: sus bloques se copian a la terminal indicada. No se ejecutan como Python ni con «Run All». Las acciones de instalación requieren interacción y pueden solicitar reinicios. En Linux nativo con Docker Engine y Compose ya instalados, comienza en el paso 3.
El montaje es didáctico, sin autenticación Kerberos y con procesos root dentro de los contenedores para simplificar los permisos de los volúmenes. El portal se publica únicamente en localhost. Los cuatro contenedores comparten hardware: esto simula fallos de servicios, no tres servidores físicos independientes.
1. Preparar Ubuntu en WSL2
Terminal: PowerShell de Windows. Comprueba primero lo que ya existe:
wsl --version
wsl --list --verboseSi Ubuntu ya aparece con VERSION 2, no vuelvas a instalarlo. Si falta WSL o Ubuntu, abre PowerShell como administrador y ejecuta:
wsl --install -d Ubuntu-24.04Reinicia Windows si se solicita. Abre Ubuntu desde Inicio y completa la creación de usuario y contraseña Linux. La contraseña no muestra caracteres mientras la escribes.
Para actualizar WSL y confirmar la distribución:
wsl --update
wsl --list --verboseSi la distribución aparece con versión 1, utiliza su nombre exacto en la conversión; por ejemplo:
wsl --set-version Ubuntu-24.04 2Comprobación: Ubuntu inicia y figura como WSL2. Documentación de Microsoft.
2. Descargar e instalar Docker Desktop
En Windows, abre la página oficial de instalación de Docker Desktop y descarga el instalador para Windows x86_64. Ejecuta el instalador y elige el backend WSL2 cuando esté disponible. Completa la instalación y los reinicios solicitados.
Abre Docker Desktop desde Inicio y espera a que el motor termine de arrancar. En su configuración, comprueba General → Use the WSL 2 based engine y activa Ubuntu en Resources → WSL Integration. Aplica los cambios. Los nombres pueden variar entre versiones. Debes trabajar con contenedores Linux.
No instales además otro Docker Engine dentro de Ubuntu para seguir esta ruta: usaremos el motor de Docker Desktop desde WSL. Consulta la guía oficial de integración WSL si la distribución no aparece.
Comprobación: Docker Desktop está abierto y Ubuntu tiene la integración habilitada. Tener instalado el programa no significa que el motor esté iniciado.
3. Verificar Docker desde Ubuntu
Terminal: Ubuntu/Bash. Desde ahora todos los comandos son de Bash, salvo indicación contraria.
docker version
docker compose version
docker info --format '{{.OSType}} / {{.Architecture}}'docker version debe mostrar Client y Server. El sistema del servidor debe ser linux. Este laboratorio utiliza una imagen para x86-64/amd64; los equipos ARM requieren comprobar soporte o emulación por separado.
Descarga y ejecuta la imagen de comprobación:
docker pull hello-world:latest
docker run --rm hello-world:latestResultado esperado: un mensaje que comienza con Hello from Docker!. --rm elimina ese contenedor de prueba al finalizar, pero conserva la imagen descargada. Si esto falla, resuelve Docker antes de continuar con Hadoop.
4. Crear el directorio de trabajo
mkdir -p ~/hdfs-docker-lab/config
cd ~/hdfs-docker-lab
pwdLa ruta debe estar dentro del home de Ubuntu, por ejemplo /home/ana/hdfs-docker-lab. Conserva esta terminal abierta. Si abres otra, ejecuta de nuevo cd ~/hdfs-docker-lab antes de utilizar Compose.
Los siguientes bloques crean archivos en esta carpeta. Si retomas un laboratorio existente, revisa sus configuraciones antes de sobrescribirlas.
5. Descargar explícitamente la imagen de Hadoop
docker pull apache/hadoop:3.4.1
docker image ls apache/hadoop
docker image inspect apache/hadoop:3.4.1 --format '{{json .RepoDigests}}'La descarga puede tardar: Docker obtiene y descomprime varias capas. Espera a que termine sin errores. Guarda el digest mostrado si necesitas registrar exactamente qué imagen utilizaste.
Una imagen, cuatro contenedores. NameNode y DataNodes utilizan el mismo software; cambian el comando de arranque y el volumen asignado. No necesitas descargar cuatro imágenes diferentes, ni imágenes de Spark o YARN. La etiqueta fijada es una decisión de reproducibilidad del laboratorio, no una afirmación de que sea la versión más reciente. Repositorio de imágenes de Apache.
Comprueba también que el ejecutable y las rutas esperadas están disponibles:
docker run --rm --entrypoint /bin/bash apache/hadoop:3.4.1 -c \
'command -v hdfs && hdfs version && test -d /opt/hadoop/etc/hadoop'6. Configurar la dirección del NameNode
Los tres archivos que crean las secciones 6, 7 y 8 (config/core-site.xml, config/hdfs-site.xml y compose.yaml) están reunidos en hdfs-lab-config.zip. Descárgalo y cópialo a ~/hdfs-docker-lab (desde WSL, la carpeta Descargas de Windows está en /mnt/c/Users/<tu-usuario>/Downloads/), descomprímelo allí con unzip -o hdfs-lab-config.zip (si Ubuntu no tiene unzip: sudo apt install -y unzip) y sigue en la sección 9. El contenido es el mismo de los bloques de estas tres secciones; léelas de todos modos, porque explican qué hace cada parámetro.
Copia el bloque completo, incluida la línea final EOF:
cat > config/core-site.xml <<'EOF'
<?xml version="1.0"?>
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://namenode:9000</value>
</property>
</configuration>
EOFnamenode será el nombre del servicio dentro de la red de Compose. El puerto 9000 es para comunicación HDFS/RPC en este laboratorio; el navegador utilizará 9870.
7. Configurar los directorios persistentes y las réplicas
cat > config/hdfs-site.xml <<'EOF'
<?xml version="1.0"?>
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///data/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///data/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.http-address</name>
<value>0.0.0.0:9870</value>
</property>
</configuration>
EOF/data/name y /data/data son rutas internas de los contenedores. Compose las asociará con volúmenes persistentes separados. El factor 3 indica el número deseado de copias por bloque.
8. Definir el clúster con Compose
cat > compose.yaml <<'EOF'
name: hdfs-lab
x-hadoop: &hadoop
image: apache/hadoop:3.4.1
user: "0:0"
entrypoint: ["/bin/bash", "-c"]
environment:
HADOOP_CONF_DIR: /opt/hadoop/etc/hadoop
HADOOP_HEAPSIZE_MAX: "512"
services:
namenode:
<<: *hadoop
hostname: namenode
command:
- |
set -e
if [ ! -f /data/name/current/VERSION ]; then
hdfs namenode -format -nonInteractive
fi
exec hdfs namenode
ports:
- "127.0.0.1:9870:9870"
volumes:
- ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro
- ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml:ro
- namenode_data:/data/name
datanode1:
<<: *hadoop
hostname: datanode1
command: ["exec hdfs datanode"]
depends_on:
- namenode
volumes:
- ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro
- ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml:ro
- datanode1_data:/data/data
datanode2:
<<: *hadoop
hostname: datanode2
command: ["exec hdfs datanode"]
depends_on:
- namenode
volumes:
- ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro
- ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml:ro
- datanode2_data:/data/data
datanode3:
<<: *hadoop
hostname: datanode3
command: ["exec hdfs datanode"]
depends_on:
- namenode
volumes:
- ./config/core-site.xml:/opt/hadoop/etc/hadoop/core-site.xml:ro
- ./config/hdfs-site.xml:/opt/hadoop/etc/hadoop/hdfs-site.xml:ro
- datanode3_data:/data/data
volumes:
namenode_data:
datanode1_data:
datanode2_data:
datanode3_data:
EOFLa sección x-hadoop reúne opciones compartidas. Cada servicio inicia un proceso HDFS en primer plano. Se reemplaza el entrypoint de la imagen para utilizar directamente nuestros XML y controlar explícitamente el primer formateo.
El NameNode se formatea solo si falta current/VERSION; un reinicio normal conserva el namespace. No formatees manualmente un NameNode con datos existentes. Los DataNodes tienen volúmenes independientes aunque usen la misma ruta interna. depends_on ordena el inicio, pero no garantiza que HDFS ya esté listo.
9. Validar e iniciar
docker compose config --quiet
docker compose config --images
docker compose pull
docker compose up -d
docker compose ps -aLa primera orden no imprime nada si el YAML es válido. pull verifica las imágenes declaradas y reutiliza las capas ya descargadas. up -d crea la red, los volúmenes y los contenedores en segundo plano.
Resultado esperado: los cuatro servicios figuran en estado Up. Eso confirma procesos en ejecución, pero todavía debemos comprobar que los DataNodes se registraron.
docker compose logs --tail=60 namenode datanode1 datanode2 datanode3
docker compose exec namenode hdfs dfsadmin -report
docker compose exec namenode hdfs dfsadmin -report | grep -E "Live datanodes|^Name:|^Configured Capacity"Espera a que el reporte indique Live datanodes (3); si el arranque no terminó, repite el reporte. No avances con menos de tres nodos vivos. Si aparece Exited, revisa sus logs.
Después espera la salida del modo seguro de arranque:
docker compose exec namenode hdfs dfsadmin -safemode waitSi la espera no termina, consulta el reporte y los logs desde otra terminal; no fuerces la salida del modo seguro para ocultar un problema.
10. Abrir el portal de HDFS
Abre en el navegador de Windows http://localhost:9870.
En Overview, identifica la versión y el resumen del sistema. En Datanodes, comprueba que aparecen tres nodos. Desde Utilities → Browse the file system, abre el explorador. La raíz puede estar vacía porque todavía no hemos cargado datos.
Las capturas siguientes son referencias de la documentación de Arenadata, no resultados de tu ejecución. Su distribución y configuración HA difieren de este laboratorio.


La navegación del namespace utiliza el NameNode. Algunas operaciones web sobre el contenido, como descargar o previsualizar, redirigen a un DataNode cuyo nombre interno no resuelve desde Windows. En este montaje realiza las transferencias con los comandos dentro de Docker; publicar únicamente el puerto 9870 no expone todos los endpoints de datos.
11. Crear y subir un archivo pequeño
printf 'ciudad,ventas\nBogota,100\nMedellin,80\nCali,60\n' > ventas.csv
cat ventas.csv
docker compose cp ventas.csv namenode:/tmp/ventas.csv
docker compose exec namenode hdfs dfs -mkdir -p /curso/datos
docker compose exec namenode hdfs dfs -put -f /tmp/ventas.csv /curso/datos/ventas.csv
docker compose exec namenode hdfs dfs -ls /curso/datos
docker compose exec namenode hdfs dfs -cat /curso/datos/ventas.csvHay tres ubicaciones distintas: ventas.csv está en Ubuntu; /tmp/ventas.csv es una copia local dentro del contenedor; /curso/datos/ventas.csv está en HDFS. docker compose cp no sube por sí solo un archivo al sistema distribuido. Esa operación la realiza hdfs dfs -put. La opción -f permite reemplazar este archivo de práctica al repetir el paso.
Resultado esperado: aparecen el encabezado y las tres ciudades. En el portal, navega a /curso/datos para ver el archivo.
12. Observar bloques y réplicas con un archivo de 300 MiB
Genera un archivo de prueba de ceros. Sirve para estudiar almacenamiento, no para medir rendimiento representativo:
dd if=/dev/zero of=archivo_300MiB.bin bs=1M count=300 status=progress
docker compose cp archivo_300MiB.bin namenode:/tmp/archivo_300MiB.bin
docker compose exec namenode hdfs dfs -put -f /tmp/archivo_300MiB.bin /curso/datos/archivo_300MiB.bin
docker compose exec namenode hdfs dfs -setrep -w 3 /curso/datos/archivo_300MiB.bin
docker compose exec namenode hdfs fsck /curso/datos/archivo_300MiB.bin -files -blocks -locations
docker compose exec namenode hdfs dfs -du -h /curso/datos/archivo_300MiB.binResultado esperado con bloques de 128 MiB: tres bloques lógicos de 128, 128 y 44 MiB, cada uno con tres réplicas. El contenido ocupa 300 MiB lógicos y aproximadamente 900 MiB con replicación. du muestra tamaño lógico y espacio consumido con réplicas; el espacio físico total incluye además otros gastos. El comando fsck debe terminar indicando HEALTHY.
Con solo tres DataNodes, cada nodo termina guardando una copia de cada bloque de este archivo. Para observar colocación sobre un subconjunto de nodos necesitarías más DataNodes que el factor de replicación. Este laboratorio tampoco configura racks físicos.
13. Detener un DataNode y comprobar la lectura
docker compose stop datanode3
docker compose ps -a
docker compose exec namenode hdfs dfs -cat /curso/datos/ventas.csv
docker compose exec namenode hdfs dfsadmin -reportEl archivo debe seguir siendo legible desde otras réplicas; puede haber demora mientras el cliente evita la réplica detenida. El portal y el NameNode no declaran un nodo muerto instantáneamente: la detección puede tardar varios minutos con los parámetros predeterminados. Repite el reporte más tarde y registra el cambio.
Con dos nodos disponibles no se pueden mantener tres réplicas en DataNodes distintos. Un archivo puede seguir siendo legible aunque esté subreplicado. Reinicia el servicio:
docker compose start datanode3
docker compose exec namenode hdfs dfsadmin -report
docker compose exec namenode hdfs dfs -setrep -w 3 /curso/datos/archivo_300MiB.bin
docker compose exec namenode hdfs fsck /curso/datos/archivo_300MiB.bin -files -blocks -locationsComprobación: vuelven los tres nodos y se alcanza el factor 3. Detener el contenedor no borró su volumen; esta prueba no equivale a destruir su disco.
14. Recuperar un archivo en Ubuntu
docker compose exec namenode hdfs dfs -get -f /curso/datos/ventas.csv /tmp/ventas_recuperadas.csv
docker compose cp namenode:/tmp/ventas_recuperadas.csv ./ventas_recuperadas.csv
diff ventas.csv ventas_recuperadas.csvdiff no produce salida si ambos archivos coinciden. Así verificas el recorrido completo: Ubuntu → contenedor → HDFS → contenedor → Ubuntu.
15. Apagar y demostrar persistencia
docker compose down
docker volume ls --filter label=com.docker.compose.project=hdfs-lab
docker compose up -dEspera a que el reporte muestre tres nodos y termine el modo seguro, como en el paso 9. Después:
docker compose exec namenode hdfs dfs -ls /curso/datos
docker compose exec namenode hdfs dfs -cat /curso/datos/ventas.csvLos archivos deben seguir allí. down elimina los contenedores y la red, pero conserva los volúmenes nombrados. Para cerrar la sesión de trabajo:
docker compose downNo uses docker compose down -v si quieres conservar el laboratorio: esa variante elimina los volúmenes del proyecto y sus datos. No hace falta ejecutarla para completar esta práctica.
16. Diagnóstico de problemas habituales
| Síntoma | Qué revisar |
|---|---|
docker: command not found en Ubuntu |
Instala Docker Desktop y activa la integración con esa distribución WSL. Reabre Ubuntu. |
| No se puede conectar al daemon | Inicia Docker Desktop y espera el motor; confirma Client y Server con docker version. |
no matching manifest |
Revisa arquitectura; este laboratorio está dirigido a x86-64. |
| Descarga rechazada o interrumpida | Comprueba internet, proxy y espacio; si Docker Hub pide autenticación, usa docker login interactivamente y repite pull. |
no configuration file provided |
Ejecuta cd ~/hdfs-docker-lab y comprueba que existe compose.yaml. |
| Error YAML | Conserva la indentación de espacios y copia el bloque completo; usa docker compose config --quiet. |
| Puerto 9870 ocupado | Cambia solo el puerto del host a 127.0.0.1:9871:9870, ejecuta up -d y abre localhost:9871. |
| Menos de tres DataNodes | Revisa docker compose ps -a y los logs del servicio ausente. |
Error Incompatible clusterIDs |
Puede haberse recreado el namespace conservando DataNodes antiguos; detén el laboratorio y revisa qué volúmenes pertenecen al mismo clúster. No reformatees a ciegas. |
| Contenedor termina con código 137 | Comprueba memoria disponible y límites de WSL/Docker; puede haber intervenido el sistema por falta de memoria. |
SafeModeException |
Espera el arranque y comprueba registro de nodos y bloques. |
| Portal abre, pero falla descarga web | La redirección al DataNode usa nombres internos; realiza hdfs dfs -get dentro del contenedor y luego docker compose cp. |
Para recopilar evidencia sin modificar HDFS:
docker compose ps -a
docker compose logs --tail=100 namenode datanode1 datanode2 datanode3
docker compose exec namenode hdfs dfsadmin -report17. Evidencias y preguntas de cierre
Entrega capturas o salidas de: imagen descargada y digest; cuatro servicios iniciados; reporte con tres DataNodes; archivo visible en el portal; fsck con tres bloques y sus ubicaciones; lectura con un nodo detenido; lectura después de recrear los contenedores.
- ¿Por qué una sola imagen permite iniciar cuatro servicios?
- ¿Qué diferencia hay entre copiar un archivo al contenedor y subirlo a HDFS?
- ¿Por qué el archivo de 300 MiB ocupa cerca de 900 MiB de contenido replicado?
- ¿Por qué dos DataNodes pueden permitir leer, pero no satisfacer el factor 3?
- ¿Qué conserva los datos cuando desaparecen los contenedores?
Respuestas orientativas: la imagen contiene el software común y cada comando elige un proceso; HDFS necesita una operación de su cliente para distribuir bloques; cada bloque tiene tres copias; hacen falta tres destinos distintos; los volúmenes nombrados conservan los datos y metadatos.
Referencias y estado de validación
- Instalar WSL — Microsoft.
- Instalar Docker Desktop en Windows.
- Integración de Docker Desktop con WSL.
- Imagen Apache Hadoop y etiquetas.
- Configuración de Hadoop 3.4.1.
- Arquitectura HDFS.
Las salidas descritas son resultados esperados, no una ejecución registrada en este notebook. La validación realizada durante la elaboración se limita a la estructura de los archivos y a los controles indicados en la entrega; completar las comprobaciones del laboratorio valida el funcionamiento en tu equipo.