Listado de la etiqueta: volumenes

Cuando perdí datos de producción por no usar volúmenes (y cómo no repetirlo)

Era viernes por la tarde. Reinicié un contenedor de PostgreSQL que habíamos levantado «temporalmente» hacía tres meses. En segundos entendí el error: los datos vivían dentro del contenedor, no en un volumen. Tres meses de datos del cliente, gone. Esa tarde aprendí para siempre qué es la persistencia en Docker.

El problema: los contenedores son efímeros por diseño

Cuando Docker crea un contenedor, agrega una capa de escritura sobre la imagen base. Todo lo que el proceso escribe va ahí. Cuando el contenedor se destruye, esa capa desaparece con él. Es intencional: los contenedores son desechables. El problema surge cuando guardamos datos importantes en esa capa temporal.

# Demostración del problema:
docker run -d --name mi-postgres postgres:16
docker exec -it mi-postgres psql -U postgres -c "CREATE TABLE clientes (id serial, nombre text);"
docker exec -it mi-postgres psql -U postgres -c "INSERT INTO clientes VALUES (1, 'Empresa ABC');"

# Destruir el contenedor...
docker rm -f mi-postgres

# Volver a crearlo...
docker run -d --name mi-postgres postgres:16
docker exec -it mi-postgres psql -U postgres -c "SELECT * FROM clientes;"
# ERROR: relation "clientes" does not exist
# Los datos desaparecieron.

Las tres formas de manejar datos en Docker

TipoDónde viveGestionado porCaso de uso
Volumes/var/lib/docker/volumes/DockerBases de datos, datos persistentes en producción
Bind MountsCualquier path del hostVosDesarrollo local, compartir código
tmpfs mountsRAM del hostDockerDatos sensibles temporales, caché efímera

Volúmenes nombrados: la forma correcta para producción

Los volúmenes son el mecanismo preferido para datos persistentes. Docker los gestiona completamente: sabe dónde están, los protege de eliminaciones accidentales y los puede mover entre contenedores fácilmente.

# Crear un volumen nombrado
docker volume create postgres-data

# Usarlo con PostgreSQL
docker run -d   --name mi-postgres   -e POSTGRES_PASSWORD=secreto   -e POSTGRES_DB=miapp   -v postgres-data:/var/lib/postgresql/data   -p 5432:5432   --restart=unless-stopped   postgres:16-alpine

# Ahora los datos sobreviven al contenedor:
docker rm -f mi-postgres
docker run -d   --name mi-postgres   -e POSTGRES_PASSWORD=secreto   -v postgres-data:/var/lib/postgresql/data   postgres:16-alpine
# ✅ Los datos siguen ahí

Comandos de gestión de volúmenes

docker volume ls                          # listar volúmenes
docker volume inspect postgres-data       # detalle de un volumen
docker volume rm postgres-data            # eliminar (solo si no está en uso)
docker volume prune                       # eliminar todos los no usados

Bind Mounts: para desarrollo local

Los bind mounts montan un directorio del host directamente en el contenedor. Los uso mucho en desarrollo: edito el código en mi máquina y el contenedor lo ve en tiempo real, sin necesidad de hacer rebuild.

# Desarrollo de API .NET con hot reload
docker run -d   --name mi-api-dev   -v $(pwd):/app   -w /app   -p 5000:80   -e ASPNETCORE_ENVIRONMENT=Development   mcr.microsoft.com/dotnet/sdk:8.0   dotnet watch run

# Desarrollo Node.js con nodemon
docker run -d   --name mi-node-dev   -v $(pwd):/app   -w /app   -p 3000:3000   node:20-alpine   sh -c "npm install && npm run dev"

Backup y restauración de volúmenes

Después del incidente del viernes, implementé backups automáticos de todos los volúmenes de producción. La estrategia más confiable que encontré:

# Backup de un volumen a un archivo tar
docker run --rm   -v postgres-data:/data   -v $(pwd)/backups:/backups   alpine   tar czf /backups/postgres-$(date +%Y%m%d_%H%M%S).tar.gz -C /data .

# Restaurar desde backup
docker run --rm   -v postgres-data:/data   -v $(pwd)/backups:/backups   alpine   tar xzf /backups/postgres-20260311_030000.tar.gz -C /data

# Backup directo de PostgreSQL (más limpio para DBs)
docker exec mi-postgres   pg_dump -U postgres miapp > backup_$(date +%Y%m%d).sql

La regla que aplico siempre

Si el dato importa, va en un volumen. Sin excepción. Bases de datos, archivos subidos por usuarios, certificados, configuraciones que cambian en runtime. Todo lo que no quiero perder cuando hago docker rm -f va en un volumen nombrado. El viernes que perdí esos datos fue la última vez que cometí ese error.


Artículo anterior: Ciclo de vida de un contenedor | Serie Docker Completo | Próximo: Redes en Docker →


Artículo anterior: docker run y todo lo que nadie te explica del ciclo de vida de un contenedor | Serie Docker Completo | Próximo: Redes en Docker: de ‘no puedo conectar mis contenedores’ a entenderlo de verdad →