Almacenamiento en Docker: Guía de Persistencia de Datos

Persistencia de Datos en Docker

Por defecto, los datos de un contenedor se almacenan en su capa de escritura. Cuando el contenedor es eliminado, todos estos datos se pierden permanentemente. Para solucionar esto, Docker proporciona mecanismos de persistencia de datos.

Existen dos métodos principales para lograr la persistencia:

  • Montajes de enlace (Bind Mounts): mapean directorios del host al contenedor
  • Volúmenes (Volumes): gestionados completamente por Docker

Montajes de Enlace (Bind Mounts)

Ubicación Cualquier ruta del sistema operativo host
Acceso Procesos del host pueden acceder directamente
Uso típico Entornos de desarrollo - sincronización de código

Ejemplo de montaje de enlace:

docker run -v /ruta/host:/ruta/contenedor nombre_imagen

Ejemplo práctico con MySQL:

[root@servidor ~]# docker run -itd -p 3306:3306 --name mysql-server -e MYSQL_ROOT_PASSWORD="password123" -v /datos/mysql:/var/lib/mysql mysql:8.0.42
abc123def456789...
[root@servidor ~]# ls -la /datos/mysql/
total 4096
drwxr-xr-x 1 root root 4096 ago 15 10:30 .

Volúmenes de Docker

Ubicación /var/lib/docker/volumes/
Gestión Exclusivamente por Docker
Uso recomendado Entornos de producción

Comando básico:

docker run -v nombre_volumen:/ruta/contenedor nombre_imagen

Tipos de Volúmenes

Volúmenes Nombrados: tienen un nombre específico definido por el usuario

Volúmenes Anónimos: Docker genera automáticamente un identificador hash como nombre

Creación explícita de volumen nombrado
# Paso 1: Crear el volumen manualmente
[root@servidor ~]# docker volume create db_mysql
db_mysql

# Paso 2: Verificar que fue creado
[root@servidor ~]# docker volume ls
DRIVER    VOLUME NAME
local     db_mysql

# Paso 3: Ejecutar contenedor usando el volumen
[root@servidor ~]# docker run -itd -p 3307:3306 --name mysql-product -e MYSQL_ROOT_PASSWORD="password123" -v db_mysql:/var/lib/mysql mysql:8.0.42
def789abc012...

Creación implícita de volumen nombrado

Si se especifica un volumen que no existe, Docker lo crea automáticamente:

[root@servidor ~]# docker run -itd -p 3308:3306 --name mysql-app -e MYSQL_ROOT_PASSWORD="password123" -v datos_app:/var/lib/mysql mysql:8.0.42
ghi456def789...

# Docker crea automáticamente el volumen
[root@servidor ~]# docker volume ls
DRIVER    VOLUME NAME
local     db_mysql
local     datos_app

Creación implícita de volumen anónimo
# Al omitir el nombre, Docker genera un volumen anónimo
docker run -v /ruta/interna ...

Declaración de volumen en Dockerfile

La instrucción VOLUME en Dockerfile crea automáticamente un volumen anónimo al iniciar el contenedor:

# En Dockerfile:
# VOLUME /var/lib/postgresql/data

[root@servidor docker]# docker run -itd -p 3309:3306 --name mysql-test -e MYSQL_ROOT_PASSWORD="password123" mysql:8.0.42
jkl012mno345...

[root@servidor docker]# docker volume ls
DRIVER    VOLUME NAME
local     123abc456def789... (volumen anónimo generado)
local     db_mysql
local     datos_app

Estructura de Almacenamiento de Docker

El directorio predeterminado de datos es: /var/lib/docker/

/var/lib/docker/
├── containers/    # Metadatos de contenedores (configuración, logs)
├── overlay2/      # Capas del sistema de archivos del contenedor
├── volumes/       # Almacenamiento de volúmenes
└── image/         # Metadatos de imágenes

Composición del Almacenamiento de Contenedores

  1. Capas del sistema de archivos (overlay2)
    • Almacena la capa de escritura del contenedor
    • Utiliza el sistema de archivos联合 (OverlayFS) para almacenamiento estratificado
  2. Metadatos del contenedor (containers)
    • Cada contenedor tiene un subdirectorio (nombrado con su ID)
    • Contiene: config.v2.json, hostname, hosts, logs JSON
  3. Almacenamiento de volúmenes (volumes)
    • Volúmenes nombrados: /var/lib/docker/volumes/<nombre>/_data
    • Volúmenes anónimos: /var/lib/docker/volumes/<id_random>/_data

Inspección de Docker y Volúmenes

Ver información detallada de un contenedor

[root@servidor docker]# docker inspect ghi456def789
[
    {
        "Id": "ghi456def789abc123...",
        "Created": "2025-07-01T17:25:00.123456789Z",
        "Path": "docker-entrypoint.sh",
        "Args": ["mysqld"],
        "State": {
            "Status": "running",
            "Running": true,
            ...
        },
        "Mounts": [
            {
                "Type": "volume",
                "Name": "datos_app",
                "Source": "/var/lib/docker/volumes/datos_app/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "RW": true
            }
        ],
        ...
    }
]

Filtrar información específica

# Ver directorio MergedDir
[root@servidor docker]# docker inspect ghi456def789 --format '{{.GraphDriver.Data.MergedDir}}'
/var/lib/docker/overlay2/abc123def456.../merged

# Ver mounts
[root@servidor docker]# docker inspect ghi456def789 | grep Mounts -A 15
        "Mounts": [
            {
                "Type": "volume",
                "Name": "datos_app",
                "Source": "/var/lib/docker/volumes/datos_app/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "z",
                "RW": true
            }
        ],

Comandos para volúmenes

# Listar todos los volúmenes
docker volume ls

# Inspecionar un volumen específico
docker volume inspect db_mysql

# Limpiar volúmenes sin uso
docker volume prune

Ejemplo de inspección:

[root@servidor ~]# docker volume inspect db_mysql
[
    {
        "CreatedAt": "2025-07-02T01:20:00+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/db_mysql/_data",
        "Name": "db_mysql",
        "Options": null,
        "Scope": "local"
    }
]

Uso de almacenamiento de Docker

# Mostrar uso de disco de imágenes, contenedores y volúmenes
docker system df -v

Extracción de Archivos desde Imágenes

A veces es necesario copiar archivos de una imagen sin ejecutar el contenedor:

[root@servidor config]# docker create --name contenedor-temporal mysql:8.0.42
mno789pqr012...

[root@servidor config]# docker cp contenedor-temporal:/etc/mysql/my.cnf /data/config/my.cnf
Successfully copied 2.5kB to /data/config/my.cnf

[root@servidor config]# docker rm contenedor-temporal
contenedor-temporal

Montaje de Archivos de Configuración

Para sobrescribir archivos de configuración del contenedor:

[root@servidor config]# docker run -itd -p 3310:3306 --name mysql-custom -e MYSQL_ROOT_PASSWORD="password123" -v /data/config/my.cnf:/etc/my.cnf mysql:8.0.42
stu345vwx678...

# Verificar configuración desde el host
[root@servidor config]# docker exec mysql-custom cat /etc/my.cnf
[mysqld]
bind-address = 0.0.0.0
max_connections = 300
innodb_file_per_table = 1

Reglas de Sobreescritura de Datos

Escenario Comportamiento al iniciar Ejemplo
Nuevo volumen nombrado Contenido del contenedor → volumen Inicializar base de datos
Volumen nombrado existente Contenido del volumen → contenedor Restaurar respaldo
Directorio host vacío Contenido del contenedor → host Sincronizar código en desarrollo
Directorio host no vacío Contenido del host → contenedor Configuración de producción
VOLUME en Dockerfile Crea volumen anónimo y sobrescribe Proteger datos importantes

Gestión del Ciclo de Vida de los Datos

Tipo de dato Ubicación Persiste tras eliminar contenedor
Capa de escritura del contenedor overlay2 NO - se elimina inmediatamente
Volumen nombrado volumes
Montaje de enlace Ruta especificada por usuario
Volumen anónimo volumes SÍ - requiere limpieza manual

Selección del Método de Almacenamiento

Recomendaciones según el caso de uso:

Escenario Solución recomendada Notas importantes
Archivos de configuración Montaje de enlace Usar modo solo lectura (ro)
Caché temporal Volumen anónimo Combinar con --rm para limpieza automática
Datos compartidos entre contenedores Volumen nombrado Considerar problemas de escritura concurrente
Almacenamiento de base de datos Volumen nombrado + respaldos periódicos Verificar que el driver sea adecuado para el tipo de E/S

Importante: Evitar almacenar datos importantes únicamente en la capa de escritura del contenedor.

Etiquetas: Docker volumes Storage persistence bind-mounts

Publicado el 8-3 17:23