Curso Docker #4: Volumenes Docker — Datos Persistentes
Bienvenido al Curso de Docker - Parte 4 de 10

Fuente: Wikimedia Commons
¡Bienvenido a la Parte 4 del Curso de Docker! En los articulos anteriores aprendiste a crear contenedores y construir imagenes. Pero hay un problema que no hemos resuelto: cuando eliminas un contenedor, todos los datos que genero se pierden.
En este articulo vas a aprender a usar volumenes Docker para persistir datos. Esto es fundamental para bases de datos, archivos de configuracion, logs y cualquier dato que necesites conservar mas alla del ciclo de vida de un contenedor.
Por que los contenedores pierden datos
Cada contenedor tiene su propio sistema de archivos efimero. Cuando un contenedor se crea, Docker le asigna una capa de escritura sobre las capas de solo lectura de la imagen. Cualquier archivo que crees o modifiques dentro del contenedor se almacena en esa capa.
El problema: cuando el contenedor se elimina (docker rm), esa capa de escritura se destruye junto con todos los datos.
Veamos esto en la practica:
1# Crear un contenedor y escribir datos
2docker run -it --name test-datos alpine sh
3
4# Dentro del contenedor:
5echo "Datos importantes" > /datos.txt
6cat /datos.txt
7# Datos importantes
8exit
9
10# El contenedor esta detenido pero los datos aun existen
11docker start test-datos
12docker exec test-datos cat /datos.txt
13# Datos importantes
14
15# Ahora eliminamos el contenedor
16docker rm -f test-datos
17
18# Creamos uno nuevo con el mismo nombre
19docker run -it --name test-datos alpine sh
20
21# Los datos ya no existen!
22cat /datos.txt
23# cat: can't open '/datos.txt': No such file or directory
24exit
25docker rm test-datos
docker stop) NO borra los datos. Los datos se pierden solo cuando el contenedor se elimina (docker rm). Sin embargo, no deberias depender de esto — siempre usa volumenes para datos que quieras conservar.
Tipos de almacenamiento en Docker
Docker ofrece tres mecanismos para persistir datos fuera del sistema de archivos efimero del contenedor:
1. Named Volumes (Volumenes con nombre)
Son la opcion recomendada por Docker. Docker gestiona completamente donde se almacenan los datos en el host. Son portables y faciles de usar.
2. Bind Mounts (Montajes de enlace)
Montan un directorio o archivo especifico de tu maquina dentro del contenedor. Son utiles para desarrollo porque reflejan los cambios en tiempo real.
3. tmpfs Mounts
Almacenan datos en la memoria RAM del host, nunca en disco. Son utiles para datos temporales sensibles que no deben persistir.
| Caracteristica | Named Volume | Bind Mount | tmpfs |
|---|---|---|---|
| Donde viven los datos | Docker los gestiona | Ruta en el host | Memoria RAM |
| Persisten al eliminar contenedor | Si | Si | No |
| Compartir entre contenedores | Si | Si | No |
| Rendimiento | Bueno | Nativo | Excelente |
| Uso recomendado | Produccion | Desarrollo | Datos sensibles temporales |
Named Volumes: volumenes con nombre
Los named volumes son la forma mas segura y portatil de persistir datos en Docker. Veamos como usarlos:
Crear y gestionar volumenes
1# Crear un volumen
2docker volume create mis-datos
3
4# Listar volumenes
5docker volume ls
6
7# Inspeccionar un volumen (ver donde se almacena)
8docker volume inspect mis-datos
9# [
10# {
11# "CreatedAt": "2025-01-15T10:30:00Z",
12# "Driver": "local",
13# "Labels": {},
14# "Mountpoint": "/var/lib/docker/volumes/mis-datos/_data",
15# "Name": "mis-datos",
16# "Options": {},
17# "Scope": "local"
18# }
19# ]
20
21# Eliminar un volumen
22docker volume rm mis-datos
23
24# Eliminar todos los volumenes que no estan en uso
25docker volume prune
Usar un volumen en un contenedor
1# Montar un named volume con -v
2docker run -d --name app-con-datos \
3 -v mis-datos:/app/datos \
4 alpine sleep 3600
5
6# Explicacion:
7# -v mis-datos:/app/datos
8# mis-datos = nombre del volumen (se crea automaticamente si no existe)
9# /app/datos = ruta dentro del contenedor donde se monta
10
11# Escribir datos
12docker exec app-con-datos sh -c "echo 'Hola volumen!' > /app/datos/saludo.txt"
13
14# Verificar que los datos estan ahi
15docker exec app-con-datos cat /app/datos/saludo.txt
16# Hola volumen!
17
18# Eliminar el contenedor
19docker rm -f app-con-datos
20
21# Crear un NUEVO contenedor con el MISMO volumen
22docker run -d --name app-nueva \
23 -v mis-datos:/app/datos \
24 alpine sleep 3600
25
26# Los datos persisten!
27docker exec app-nueva cat /app/datos/saludo.txt
28# Hola volumen!
29
30# Limpiar
31docker rm -f app-nueva
-v nombre:/ruta y el volumen no existe, Docker lo crea automaticamente. No necesitas ejecutar docker volume create primero, aunque hacerlo explicitamente es una buena practica para entornos de produccion.
Bind Mounts: montajes desde el host
Los bind mounts conectan un directorio de tu maquina directamente al contenedor. Son ideales para desarrollo porque los cambios que hagas en tu editor se reflejan instantaneamente dentro del contenedor.
1# Crear un directorio en tu maquina
2mkdir -p ~/docker-demo/src
3
4# Crear un archivo
5echo "<h1>Hola desde el host!</h1>" > ~/docker-demo/src/index.html
6
7# Montar el directorio en un contenedor de Nginx
8docker run -d --name web-dev \
9 -p 8080:80 \
10 -v ~/docker-demo/src:/usr/share/nginx/html:ro \
11 nginx
12
13# Explicacion:
14# ~/docker-demo/src = ruta ABSOLUTA en tu maquina
15# /usr/share/nginx/html = ruta dentro del contenedor
16# :ro = read-only (el contenedor no puede modificar)
17
18# Abre http://localhost:8080 — veras tu HTML
19
20# Modifica el archivo desde tu maquina
21echo "<h1>Contenido actualizado!</h1>" > ~/docker-demo/src/index.html
22
23# Recarga el navegador — veras el cambio inmediatamente!
24
25# Limpiar
26docker rm -f web-dev
$(pwd) para obtener el directorio actual: -v $(pwd)/src:/app/src. En Windows con PowerShell usa $PWD.
Bind Mounts para desarrollo con hot-reload
Un caso de uso muy comun es montar tu codigo fuente para que los cambios se reflejen sin reconstruir la imagen:
1# Desarrollo con Node.js y hot-reload
2docker run -d --name node-dev \
3 -p 3000:3000 \
4 -v $(pwd)/src:/app/src \
5 -v $(pwd)/package.json:/app/package.json \
6 mi-node-app:dev
7
8# Ahora cada vez que edites archivos en src/, el contenedor ve los cambios
tmpfs Mounts: almacenamiento en memoria
Los tmpfs mounts almacenan datos en la RAM del host. Son utiles para datos sensibles que no deben escribirse en disco:
1# Montar tmpfs
2docker run -d --name app-segura \
3 --tmpfs /app/temp:rw,size=64m \
4 alpine sleep 3600
5
6# Los datos en /app/temp estan en RAM
7docker exec app-segura sh -c "echo 'secreto' > /app/temp/token.txt"
8docker exec app-segura cat /app/temp/token.txt
9# secreto
10
11# Al reiniciar o eliminar el contenedor, los datos desaparecen
12docker rm -f app-segura
Compartir datos entre contenedores
Los volumenes permiten que multiples contenedores compartan datos. Esto es util para arquitecturas donde un contenedor genera datos y otro los consume:
1# Crear un volumen compartido
2docker volume create datos-compartidos
3
4# Contenedor 1: escribe datos
5docker run -d --name escritor \
6 -v datos-compartidos:/datos \
7 alpine sh -c "while true; do date >> /datos/log.txt; sleep 5; done"
8
9# Contenedor 2: lee datos (en otro terminal)
10docker run -it --name lector \
11 -v datos-compartidos:/datos:ro \
12 alpine sh
13
14# Dentro del contenedor lector:
15cat /datos/log.txt
16# Veras las fechas que el escritor esta generando!
17tail -f /datos/log.txt
18# Veras nuevas lineas cada 5 segundos
19exit
20
21# Limpiar
22docker rm -f escritor lector
23docker volume rm datos-compartidos
Ejemplo practico: PostgreSQL con volumen persistente
El caso de uso mas comun de volumenes es persistir datos de bases de datos. Veamos como levantar PostgreSQL con un volumen para que los datos sobrevivan al contenedor:
1# Crear un volumen para PostgreSQL
2docker volume create postgres-datos
3
4# Ejecutar PostgreSQL con el volumen
5docker run -d --name mi-postgres \
6 -e POSTGRES_USER=admin \
7 -e POSTGRES_PASSWORD=secreto123 \
8 -e POSTGRES_DB=mi_base \
9 -v postgres-datos:/var/lib/postgresql/data \
10 -p 5432:5432 \
11 postgres:16-alpine
12
13# Esperar a que PostgreSQL inicie
14docker logs -f mi-postgres
15# Busca: "database system is ready to accept connections"
16# Presiona Ctrl+C para salir de los logs
17
18# Conectarse y crear datos
19docker exec -it mi-postgres psql -U admin -d mi_base
20
21# Dentro de psql:
22# CREATE TABLE usuarios (id SERIAL PRIMARY KEY, nombre VARCHAR(100));
23# INSERT INTO usuarios (nombre) VALUES ('Ana'), ('Carlos'), ('Maria');
24# SELECT * FROM usuarios;
25# id | nombre
26# ----+--------
27# 1 | Ana
28# 2 | Carlos
29# 3 | Maria
30# \q
Ahora veamos que los datos persisten:
1# Eliminar el contenedor (simulando un fallo)
2docker rm -f mi-postgres
3
4# Crear un nuevo contenedor con el MISMO volumen
5docker run -d --name mi-postgres-nuevo \
6 -e POSTGRES_USER=admin \
7 -e POSTGRES_PASSWORD=secreto123 \
8 -e POSTGRES_DB=mi_base \
9 -v postgres-datos:/var/lib/postgresql/data \
10 -p 5432:5432 \
11 postgres:16-alpine
12
13# Verificar que los datos siguen ahi
14docker exec -it mi-postgres-nuevo psql -U admin -d mi_base -c "SELECT * FROM usuarios;"
15# id | nombre
16# ----+--------
17# 1 | Ana
18# 2 | Carlos
19# 3 | Maria
20
21# Los datos sobrevivieron a la destruccion del contenedor!
/var/lib/postgresql/data es donde PostgreSQL almacena sus datos por defecto. Cada imagen de base de datos tiene su propia ruta. Para MySQL es /var/lib/mysql, para MongoDB es /data/db. Consulta la documentacion oficial de almacenamiento en Docker para mas detalles.
Estrategias de backup de volumenes
Tener datos en volumenes no es suficiente — necesitas una estrategia de backup. Aqui tienes varias opciones:
Backup manual con tar
1# Crear un backup del volumen postgres-datos
2docker run --rm \
3 -v postgres-datos:/source:ro \
4 -v $(pwd):/backup \
5 alpine tar czf /backup/postgres-backup-$(date +%Y%m%d).tar.gz -C /source .
6
7# Explicacion:
8# --rm = eliminar contenedor al terminar
9# -v postgres-datos:/source:ro = montar el volumen como solo lectura
10# -v $(pwd):/backup = montar el directorio actual para guardar el archivo
11# tar czf ... = crear archivo comprimido
12
13# Verificar el backup
14ls -lh postgres-backup-*.tar.gz
Restaurar un backup
1# Crear un nuevo volumen para restaurar
2docker volume create postgres-restaurado
3
4# Restaurar el backup
5docker run --rm \
6 -v postgres-restaurado:/target \
7 -v $(pwd):/backup:ro \
8 alpine tar xzf /backup/postgres-backup-20250115.tar.gz -C /target
9
10# Ahora puedes usar el volumen restaurado en un nuevo contenedor
11docker run -d --name pg-restaurado \
12 -e POSTGRES_USER=admin \
13 -e POSTGRES_PASSWORD=secreto123 \
14 -v postgres-restaurado:/var/lib/postgresql/data \
15 -p 5433:5432 \
16 postgres:16-alpine
Copiar archivos entre host y contenedor
1# Copiar un archivo del contenedor al host
2docker cp mi-postgres:/var/lib/postgresql/data/pg_hba.conf ./pg_hba.conf
3
4# Copiar un archivo del host al contenedor
5docker cp ./mi-config.conf mi-postgres:/etc/postgresql/
pg_dump para PostgreSQL, mysqldump para MySQL) o detiene el contenedor antes de hacer el backup con tar.
Resumen y proximo articulo
En este cuarto articulo del curso hemos aprendido:
- Por que los contenedores pierden datos cuando se eliminan
- Los tres tipos de almacenamiento: named volumes, bind mounts y tmpfs
- Como crear y gestionar volumenes con docker volume
- Como compartir datos entre multiples contenedores
- Ejemplo practico con PostgreSQL y datos persistentes
- Estrategias de backup y restauracion de volumenes
En el proximo articulo (Parte 5 de 10) aprenderemos sobre redes en Docker. Veras como los contenedores se comunican entre si, como funciona el DNS automatico y como conectar una aplicacion Node.js con una base de datos MySQL usando redes personalizadas.
¡Nos vemos en el siguiente articulo!
Comments
Sign in to leave a comment
No comments yet. Be the first!