Volúmenes y Bind Mounts en Docker
Tutorial de Volúmenes en Docker
📚 Introducción a los Volúmenes de Docker
Los volúmenes en Docker son el mecanismo preferido para persistir datos generados y utilizados por contenedores Docker. A diferencia del sistema de archivos por capas de los contenedores, los volúmenes existen completamente fuera del ciclo de vida del contenedor.
¿Por qué usar volúmenes?
Persistencia de datos: Los datos sobreviven al reinicio o eliminación del contenedor
Compartir datos: Múltiples contenedores pueden acceder al mismo volumen
Backup y migración: Fácil de hacer backup y restaurar
Mejor rendimiento: Comparado con bind mounts en algunos sistemas
Persistencia de datos: Los datos sobreviven al reinicio o eliminación del contenedor
Compartir datos: Múltiples contenedores pueden acceder al mismo volumen
Backup y migración: Fácil de hacer backup y restaurar
Mejor rendimiento: Comparado con bind mounts en algunos sistemas
🛠️ Tipos de Volúmenes
1. Volúmenes Nombrados (Named Volumes)
2. Volúmenes Anónimos (Anonymous Volumes)
3. Bind Mounts
🚀 Ejemplos Prácticos
Ejemplo 1: Crear y usar un volumen nombrado
# Crear un volumen nombrado
docker volume create mi-volumen
# Verificar que el volumen fue creado
docker volume ls
# Inspeccionar el volumen
docker volume inspect mi-volumen
# Usar el volumen en un contenedor
docker run -d --name mi-contenedor -v mi-volumen:/app/data nginx
# Verificar que el volumen está siendo usado
docker inspect mi-contenedor
# Crear un volumen nombrado
docker volume create mi-volumen
# Verificar que el volumen fue creado
docker volume ls
# Inspeccionar el volumen
docker volume inspect mi-volumen
# Usar el volumen en un contenedor
docker run -d --name mi-contenedor -v mi-volumen:/app/data nginx
# Verificar que el volumen está siendo usado
docker inspect mi-contenedorEjemplo 2: Usar volúmenes con MySQL
# Crear un volumen para MySQL
docker volume create mysql-data
# Ejecutar MySQL con el volumen
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=mi_password \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# Verificar los datos persisten
docker exec -it mysql-container mysql -pmi_password -e "CREATE DATABASE test_db;"
docker stop mysql-container
docker start mysql-container
docker exec -it mysql-container mysql -pmi_password -e "SHOW DATABASES;"
# Crear un volumen para MySQL
docker volume create mysql-data
# Ejecutar MySQL con el volumen
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=mi_password \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# Verificar los datos persisten
docker exec -it mysql-container mysql -pmi_password -e "CREATE DATABASE test_db;"
docker stop mysql-container
docker start mysql-container
docker exec -it mysql-container mysql -pmi_password -e "SHOW DATABASES;"Ejemplo 3: Bind Mount para desarrollo
# Montar un directorio local en el contenedor
docker run -d \
--name nginx-dev \
-p 8080:80 \
-v $(pwd)/html:/usr/share/nginx/html \
nginx
# Crear un archivo en el directorio local
echo "<h1>Hola desde bind mount!</h1>" > html/index.html
# Verificar en el navegador: http://localhost:8080
# Montar un directorio local en el contenedor
docker run -d \
--name nginx-dev \
-p 8080:80 \
-v $(pwd)/html:/usr/share/nginx/html \
nginx
# Crear un archivo en el directorio local
echo "<h1>Hola desde bind mount!</h1>" > html/index.html
# Verificar en el navegador: http://localhost:8080Ejemplo 4: Volumen de solo lectura
# Montar un volumen como solo lectura
docker run -d \
--name nginx-ro \
-v mi-volumen:/app/data:ro \
nginx
# Montar un volumen como solo lectura
docker run -d \
--name nginx-ro \
-v mi-volumen:/app/data:ro \
nginx📝 Usando Docker Compose con Volúmenes
docker-compose.yml ejemplo:
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- web-data:/usr/share/nginx/html
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: userpass
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
web-data:
driver: local
db-data:
driver: local
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- web-data:/usr/share/nginx/html
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: app_db
MYSQL_USER: app_user
MYSQL_PASSWORD: userpass
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
web-data:
driver: local
db-data:
driver: localEjecutar:
docker-compose up -d🔧 Comandos Esenciales para Volúmenes
Gestión de Volúmenes
# Listar volúmenes
docker volume ls
# Crear volumen
docker volume create nombre-volumen
# Inspeccionar volumen
docker volume inspect nombre-volumen
# Eliminar volumen
docker volume rm nombre-volumen
# Eliminar todos los volúmenes no utilizados
docker volume prune
# Listar volúmenes
docker volume ls
# Crear volumen
docker volume create nombre-volumen
# Inspeccionar volumen
docker volume inspect nombre-volumen
# Eliminar volumen
docker volume rm nombre-volumen
# Eliminar todos los volúmenes no utilizados
docker volume pruneBackup y Restauración
# Backup de un volumen
docker run --rm -v nombre-volumen:/data -v $(pwd):/backup alpine \
tar czf /backup/backup.tar.gz -C /data .
# Restaurar un volumen
docker run --rm -v nombre-volumen:/data -v $(pwd):/backup alpine \
sh -c "rm -rf /data/* && tar xzf /backup/backup.tar.gz -C /data"
# Backup de un volumen
docker run --rm -v nombre-volumen:/data -v $(pwd):/backup alpine \
tar czf /backup/backup.tar.gz -C /data .
# Restaurar un volumen
docker run --rm -v nombre-volumen:/data -v $(pwd):/backup alpine \
sh -c "rm -rf /data/* && tar xzf /backup/backup.tar.gz -C /data"🎯 Mejores Prácticas
1. Usar volúmenes nombrados en producción
# ✅ Recomendado
-v mi-volumen-prod:/app/data
# ❌ Evitar en producción
-v /app/data
# ✅ Recomendado
-v mi-volumen-prod:/app/data
# ❌ Evitar en producción
-v /app/data2. Especificar drivers de volumen cuando sea necesario
docker volume create --driver local \
--opt type=none \
--opt device=/path/to/data \
--opt o=bind \
nombre-volumen
docker volume create --driver local \
--opt type=none \
--opt device=/path/to/data \
--opt o=bind \
nombre-volumen3. Usar volúmenes para datos críticos
# Para bases de datos
-v db-data:/var/lib/mysql
# Para uploads de usuarios
-v uploads-data:/app/uploads
# Para bases de datos
-v db-data:/var/lib/mysql
# Para uploads de usuarios
-v uploads-data:/app/uploads4. Limpiar volúmenes no utilizados regularmente
docker volume prune
docker volume prune🚨 Solución de Problemas Comunes
Verificar uso de volúmenes
# Ver qué contenedores usan un volumen
docker ps -a --filter volume=nombre-volumen
# Ver espacio usado por volúmenes
docker system df -v
# Ver qué contenedores usan un volumen
docker ps -a --filter volume=nombre-volumen
# Ver espacio usado por volúmenes
docker system df -vDepurar problemas de permisos
# Inspeccionar el volumen
docker volume inspect nombre-volumen
# Ver contenido del volumen
docker run --rm -v nombre-volumen:/data alpine ls -la /data
# Inspeccionar el volumen
docker volume inspect nombre-volumen
# Ver contenido del volumen
docker run --rm -v nombre-volumen:/data alpine ls -la /dataRecuperar datos de un volumen
# Copiar datos desde un volumen
docker run --rm -v nombre-volumen:/source -v $(pwd):/backup alpine \
cp -r /source/* /backup/
# Copiar datos desde un volumen
docker run --rm -v nombre-volumen:/source -v $(pwd):/backup alpine \
cp -r /source/* /backup/📊 Comparación: Volúmenes vs Bind Mounts
Característica Volúmenes Bind Mounts Persistencia ✅ Excelente ✅ Depende del host Portabilidad ✅ Alta ❌ Baja Backup ✅ Fácil ✅ Manual Rendimiento ✅ Bueno ✅ Variable Desarrollo ✅ Bueno ✅ Excelente
| Característica | Volúmenes | Bind Mounts |
|---|---|---|
| Persistencia | ✅ Excelente | ✅ Depende del host |
| Portabilidad | ✅ Alta | ❌ Baja |
| Backup | ✅ Fácil | ✅ Manual |
| Rendimiento | ✅ Bueno | ✅ Variable |
| Desarrollo | ✅ Bueno | ✅ Excelente |
🎓 Ejercicios Prácticos
Ejercicio 1: Aplicación con persistencia
Crea un contenedor WordPress con volúmenes para la base de datos y archivos
Verifica que los datos persisten después de reiniciar
Crea un contenedor WordPress con volúmenes para la base de datos y archivos
Verifica que los datos persisten después de reiniciar
Ejercicio 2: Migración de datos
Crea un volumen con datos
Haz backup del volumen
Restaura en un nuevo volumen
Crea un volumen con datos
Haz backup del volumen
Restaura en un nuevo volumen
Ejercicio 3: Desarrollo con hot-reload
Configura un contenedor de desarrollo con bind mount
Modifica archivos locales y ve los cambios en tiempo real
Configura un contenedor de desarrollo con bind mount
Modifica archivos locales y ve los cambios en tiempo real
📋 Resumen
Volúmenes nombrados: Ideales para producción y datos críticos
Bind mounts: Perfectos para desarrollo y configuraciones
Docker Compose: Simplifica la gestión de volúmenes múltiples
Backup regular: Esencial para datos importantes
Volúmenes nombrados: Ideales para producción y datos críticos
Bind mounts: Perfectos para desarrollo y configuraciones
Docker Compose: Simplifica la gestión de volúmenes múltiples
Backup regular: Esencial para datos importantes
📁 Introducción a los Volúmenes en Docker
Los volúmenes en Docker permiten conectar carpetas y archivos del host con el contenedor, manteniendo la sincronización entre ambos. Esto es esencial para:
Desarrollo: Modificar código en tiempo real
Persistencia: Conservar datos cuando el contenedor se elimina
Compartir datos: Múltiples contenedores accediendo a los mismos archivos
🚀 Montar una Carpeta Local en el Contenedor
Ejemplo Básico: Proyecto Web
# Sintaxis básica
docker run -v ~/mi-proyecto:/var/www/html mi-imagenExplicación:
~/mi-proyecto: Ruta absoluta en tu equipo host/var/www/html: Ruta dentro del contenedormi-imagen: Imagen Docker a utilizar
Ejemplo Práctico con Nginx
# Crear directorio del proyecto
mkdir -p ~/mi-proyecto
# Crear un archivo HTML simple
echo "<h1>Mi Proyecto Web</h1>" > ~/mi-proyecto/index.html
# Ejecutar contenedor Nginx montando la carpeta
docker run -d \
--name mi-web \
-p 8080:80 \
-v ~/mi-proyecto:/usr/share/nginx/html \
nginx:alpine
# Verificar en el navegador: http://localhost:8080Modificar en Tiempo Real
# Modificar el archivo desde el host
echo "<h1>Proyecto Modificado</h1>" > ~/mi-proyecto/index.html
# Los cambios se reflejarán inmediatamente en el navegador🗄️ Persistir Datos de Base de Datos
Ejemplo con MySQL
# Crear directorio para datos de MySQL
mkdir -p ~/mysql-datos
# Ejecutar contenedor MySQL con persistencia
docker run -d \
--name mysql-db \
-e MYSQL_ROOT_PASSWORD=mi_password \
-e MYSQL_DATABASE=mi_app \
-v ~/mysql-datos:/var/lib/mysql \
mysql:5.7
# Verificar que los datos persisten
docker exec -it mysql-db mysql -pmi_password -e "SHOW DATABASES;"
# Detener y eliminar el contenedor
docker stop mysql-db
docker rm mysql-db
# Los datos permanecen en ~/mysql-datos
ls -la ~/mysql-datos/Verificar Persistencia
# Volver a crear el contenedor con los mismos datos
docker run -d \
--name mysql-db2 \
-e MYSQL_ROOT_PASSWORD=mi_password \
-v ~/mysql-datos:/var/lib/mysql \
mysql:5.7
# Verificar que la base de datos sigue existiendo
docker exec -it mysql-db2 mysql -pmi_password -e "SHOW DATABASES;"🔄 Comparación: Volúmenes Docker vs Bind Mounts
Docker Volumes (Volúmenes Gestionados)
# Crear volumen gestionado
docker volume create mi-volumen
# Usar volumen en contenedor
docker run -d \
--name web-app \
-v mi-volumen:/app/data \
nginx:alpine
# Los datos se almacenan en /var/lib/docker/volumes/ (solo accesible por Docker)Bind Mounts (Montajes Directos)
# Usar bind mount (acceso directo)
docker run -d \
--name web-app \
-v /home/usuario/mi-proyecto:/app/data \
nginx:alpine
# Los datos están directamente accesibles en tu sistema de archivosTabla Comparativa
| Característica | Docker Volumes | Bind Mounts |
|---|---|---|
| Gestión | Gestionado por Docker | Gestión manual |
| Portabilidad | Alta (backup fácil) | Baja (rutas específicas) |
| Rendimiento | Variable | Generalmente mejor |
| Caso de uso | Producción, datos críticos | Desarrollo, configuraciones |
| Ubicación | /var/lib/docker/volumes/ | Cualquier ruta del host |
🛠️ Comandos Esenciales para Gestión de Volúmenes
Gestión de Volúmenes Docker
# Listar volúmenes
docker volume ls
# Crear volumen
docker volume create mi-volumen
# Inspeccionar volumen
docker volume inspect mi-volumen
# Eliminar volumen
docker volume rm mi-volumen
# Limpiar volúmenes no utilizados
docker volume pruneEjemplos con Volúmenes Nombrados
# Crear y usar volumen nombrado
docker volume create app-data
docker run -d \
--name mi-app \
-v app-data:/app/storage \
mi-imagen
# Compartir volumen entre contenedores
docker run -d \
--name app-1 \
-v app-data:/shared-data \
mi-imagen
docker run -d \
--name app-2 \
-v app-data:/shared-data \
mi-imagen🐍 Ejemplo Práctico: Servidor Flask con Volumen
Estructura del Proyecto
~/volumenes/
├── app.py
└── Dockerfileapp.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "Hola Mundo desde Flask en Docker!"
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=3030)Dockerfile
FROM python:3.8
EXPOSE 3030
WORKDIR /app
RUN pip install flask
COPY ./app.py ./app.py
ENTRYPOINT ["python3"]
CMD ["app.py"]Construir y Ejecutar
# Navegar al directorio
cd ~/volumenes
# Construir la imagen
docker build -t volumen ./
# Ejecutar con bind mount para desarrollo
docker run -d \
-v $(pwd)/app.py:/app/app.py \
-p 5000:3030 \
--name flask-app \
volumenDesarrollo en Tiempo Real
# Modificar el archivo app.py desde el host
echo '
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "¡Mensaje Modificado en Caliente!"
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=3030)
' > app.py
# Los cambios se reflejan automáticamente en http://localhost:5000📋 Docker Compose para Gestión Simplificada
docker-compose.yml
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
- ./nginx.conf:/etc/nginx/nginx.conf:ro
database:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: app_db
volumes:
- db-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
flask-app:
build: .
ports:
- "5000:3030"
volumes:
- ./app.py:/app/app.py
depends_on:
- database
volumes:
db-data:Comandos Docker Compose
# Iniciar todos los servicios
docker-compose up -d
# Ver logs
docker-compose logs
# Detener servicios
docker-compose down
# Detener y eliminar volúmenes
docker-compose down -v🔧 Casos de Uso Avanzados
Volumen de Solo Lectura
# Montar volumen como solo lectura
docker run -d \
-v ~/config:/app/config:ro \
mi-imagenVolumen con Permisos Específicos
# Especificar usuario y permisos
docker run -d \
-v ~/data:/app/data \
--user 1000:1000 \
mi-imagenMúltiples Volúmenes
# Montar múltiples directorios
docker run -d \
-v ~/html:/var/www/html \
-v ~/config:/etc/nginx \
-v ~/logs:/var/log/nginx \
nginx:alpine🚨 Solución de Problemas Comunes
Verificar Volúmenes Montados
# Inspeccionar contenedor
docker inspect nombre-contenedor
# Ver volúmenes específicos
docker volume inspect nombre-volumen
# Listar volúmenes utilizados por contenedor
docker ps -a --format "table {{.Names}}\t{{.Mounts}}"Problemas de Permisos
# Ver permisos del directorio host
ls -la ~/mi-proyecto
# Si hay problemas de permisos, ajustar propietario
sudo chown -R $USER:$USER ~/mi-proyecto
# O ejecutar contenedor con usuario específico
docker run -d --user 1000:1000 -v ~/proyecto:/app mi-imagenBackup y Restauración
# Backup de volumen
docker run --rm -v mi-volumen:/data -v $(pwd):/backup alpine \
tar czf /backup/backup.tar.gz -C /data .
# Restaurar volumen
docker run --rm -v mi-volumen:/data -v $(pwd):/backup alpine \
sh -c "rm -rf /data/* && tar xzf /backup/backup.tar.gz -C /data"📝 Resumen de Sintaxis
Sintaxis Básica
# Bind mount
docker run -v /ruta/host:/ruta/contenedor imagen
# Volumen Docker
docker run -v nombre-volumen:/ruta/contenedor imagen
# Modificadores
docker run -v /ruta/host:/ruta/contenedor:ro # Solo lectura
docker run -v /ruta/host:/ruta/contenedor:rw # Lectura/escritura (default)Mejores Prácticas
Desarrollo: Usa Bind Mounts para sincronización en tiempo real
Producción: Usa Docker Volumes para mejor portabilidad
Datos críticos: Siempre usa volúmenes para bases de datos
Backup: Programa backups regulares de volúmenes importantes
Permisos: Verifica permisos entre host y contenedor
🎯 Conclusión
Los volúmenes y bind mounts son esenciales para:
✅ Persistencia de datos entre ciclos de vida del contenedor
✅ Desarrollo ágil con cambios en tiempo real
✅ Backup y recuperación de datos importantes
✅ Compartir datos entre múltiples contenedores
Comentarios
Publicar un comentario