# Volúmenes


Los volúmenes son almacenes de datos persistentes para contenedores, creados y gestionados por Docker. Puedes crear un volumen de forma explícita utilizando el comando `docker volume create`, o bien Docker puede crear un volumen durante la creación de un contenedor o servicio.

Cuando creas un volumen, este se almacena dentro de un directorio en el anfitrión de Docker. Cuando montas el volumen en un contenedor, este directorio es lo que se monta en el contenedor. Esto es similar a la forma en que funcionan los montajes de tipo bind, excepto que los volúmenes son gestionados por Docker y están aislados de la funcionalidad principal de la máquina anfitriona.

## Cuándo utilizar volúmenes

Los volúmenes son el mecanismo preferido para persistir los datos generados y utilizados por los contenedores de Docker. Mientras que los [montajes de tipo bind](/engine/storage/volumes/bind-mounts/) dependen de la estructura de directorios y del sistema operativo de la máquina anfitriona, los volúmenes son gestionados por completo por Docker. Los volúmenes son una buena opción para los siguientes casos de uso:

- Los volúmenes son más fáciles de respaldar o migrar que los montajes de tipo bind.
- Puedes gestionar los volúmenes utilizando comandos de la CLI de Docker o la API de Docker.
- Los volúmenes funcionan tanto en contenedores Linux como Windows.
- Los volúmenes se pueden compartir de forma más segura entre múltiples contenedores.
- Los nuevos volúmenes pueden tener su contenido precargado por un contenedor o una compilación.
- Cuando tu aplicación requiere E/S de alto rendimiento.

Los volúmenes no son una buena opción si necesitas acceder a los archivos desde el anfitrión, ya que el volumen es gestionado en su totalidad por Docker. Utiliza [montajes de tipo bind](/engine/storage/volumes/bind-mounts/) si necesitas acceder a archivos o directorios tanto desde los contenedores como desde el anfitrión.

A menudo, los volúmenes son una mejor opción que escribir datos directamente en un contenedor, ya que un volumen no aumenta el tamaño de los contenedores que lo utilizan. El uso de un volumen también es más rápido; escribir en la capa de escritura de un contenedor requiere que un [controlador de almacenamiento](/engine/storage/drivers/) gestione el sistema de archivos. El controlador de almacenamiento proporciona un sistema de archivos de unión utilizando el kernel de Linux. Esta abstracción adicional reduce el rendimiento en comparación con el uso de volúmenes, que escriben directamente en el sistema de archivos del anfitrión.

Si tu contenedor genera datos de estado no persistentes, considera utilizar un [montaje tmpfs](/engine/storage/volumes/tmpfs/) para evitar almacenar los datos en cualquier lugar de forma permanente y para aumentar el rendimiento del contenedor al evitar escribir en la capa de escritura del mismo.

Los volúmenes utilizan la propagación de montaje `rprivate` (privada recursiva) y la propagación de montaje no es configurable para los volúmenes.

## Ciclo de vida de un volumen

El contenido de un volumen existe fuera del ciclo de vida de un contenedor determinado. Cuando un contenedor se destruye, la capa de escritura se destruye con él. El uso de un volumen garantiza que los datos se persistan incluso si se elimina el contenedor que lo utiliza.

Un volumen determinado se puede montar en múltiples contenedores simultáneamente. Cuando ningún contenedor en ejecución está utilizando un volumen, este sigue estando disponible para Docker y no se elimina automáticamente. Puedes eliminar los volúmenes no utilizados utilizando `docker volume prune`.

## Montar un volumen sobre datos existentes

Si montas un _volumen no vacío_ en un directorio del contenedor en el que ya existen archivos o directorios, los archivos preexistentes quedarán ocultos por el montaje. Esto es similar a si guardaras archivos en `/mnt` en un anfitrión Linux y luego montaras una unidad USB en `/mnt`. El contenido de `/mnt` quedaría oculto por el contenido de la unidad USB hasta que esta se desmontara.

En el caso de los contenedores, no existe una forma sencilla de eliminar un montaje para volver a mostrar los archivos ocultos. Tu mejor opción es volver a crear el contenedor sin el montaje.

Si montas un _volumen vacío_ en un directorio del contenedor en el que ya existen archivos o directorios, estos archivos o directorios se propagarán (copiarán) en el volumen de forma predeterminada. Del mismo modo, si inicias un contenedor y especificas un volumen que aún no existe, se creará un volumen vacío para ti. Esta es una buena forma de precargar datos que otro contenedor necesita.

Para evitar que Docker copie los archivos preexistentes de un contenedor en un volumen vacío, utiliza la opción `volume-nocopy`; consulta [Opciones para --mount](#options-for---mount).

## Volúmenes con nombre y anónimos

Un volumen puede ser con nombre o anónimo. A los volúmenes anónimos se les asigna un nombre aleatorio que garantiza ser único dentro de un anfitrión de Docker determinado. Al igual que los volúmenes con nombre, los volúmenes anónimos persisten incluso si eliminas el contenedor que los utiliza, excepto si usas la bandera `--rm` al crear el contenedor, en cuyo caso el volumen anónimo asociado con el contenedor se destruye. Consulta [Eliminar volúmenes anónimos](/engine/storage/volumes/volumes/#remove-anonymous-volumes).

Si creas múltiples contenedores de forma consecutiva y cada uno de ellos utiliza volúmenes anónimos, cada contenedor creará su propio volumen. Los volúmenes anónimos no se reutilizan ni se comparten entre contenedores automáticamente. Para compartir un volumen anónimo entre dos o más contenedores, debes montar el volumen anónimo utilizando el ID de volumen aleatorio.

## Sintaxis

Para montar un volumen con el comando `docker run`, puedes utilizar la bandera `--mount` o `--volume`.

```console
$ docker run --mount type=volume,src=<volume-name>,dst=<mount-path>
$ docker run --volume <volume-name>:<mount-path>
```

En general, se prefiere `--mount`. La principal diferencia es que la bandera `--mount` es más explícita y admite todas las opciones disponibles.

Debes utilizar `--mount` si quieres:

- Especificar [opciones del controlador de volumen](#use-a-volume-driver)
- Montar un [subdirectorio de volumen](#mount-a-volume-subdirectory)
- Montar un volumen en un servicio de Swarm

### Opciones para --mount

La bandera `--mount` consta de múltiples pares clave-valor, separados por comas, cada uno de los cuales consiste en una tupla `<key>=<value>`. El orden de las claves no es relevante.

```console
$ docker run --mount type=volume[,src=<volume-name>],dst=<mount-path>[,<key>=<value>...]
```

Las opciones válidas para `--mount type=volume` incluyen:

| Opción | Descripción |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`, `src`                | El origen del montaje. Para volúmenes con nombre, este es el nombre del volumen. Para volúmenes anónimos, este campo se omite. |
| `destination`, `dst`, `target` | La ruta donde se monta el archivo o directorio en el contenedor. |
| `volume-subpath`               | Una ruta a un subdirectorio dentro del volumen para montar en el contenedor. El subdirectorio debe existir en el volumen antes de que el volumen se monte en un contenedor. Consulta [Montar un subdirectorio de volumen](#mount-a-volume-subdirectory). |
| `readonly`, `ro`               | Si está presente, hace que el volumen se [monte en el contenedor como de solo lectura](#use-a-read-only-volume). |
| `volume-nocopy`                | Si está presente, los datos en el destino no se copian al volumen si el volumen está vacío. Por defecto, el contenido en el destino de destino se copia en un volumen montado si está vacío. |
| `volume-opt`                   | Se puede especificar más de una vez, toma un par clave-valor que consiste en el nombre de la opción y su valor. |

```console {title="Example"}
$ docker run --mount type=volume,src=myvolume,dst=/data,ro,volume-subpath=/foo
```

### Opciones para --volume

La bandera `--volume` o `-v` consta de tres campos, separados por caracteres de dos puntos (`:`). Los campos deben estar en el orden correcto.

```console
$ docker run -v [<volume-name>:]<mount-path>[:opts]
```

En el caso de volúmenes con nombre, el primer campo es el nombre del volumen y es único en una máquina anfitriona determinada. Para volúmenes anónimos, el primer campo se omite. El segundo campo es la ruta donde se monta el archivo o directorio en el contenedor.

El tercer campo es opcional y consiste en una lista de opciones separadas por comas. Las opciones válidas para `--volume` con un volumen de datos incluyen:

| Opción | Descripción |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `readonly`, `ro` | Si está presente, hace que el volumen se [monte en el contenedor como de solo lectura](#use-a-read-only-volume). |
| `volume-nocopy`  | Si está presente, los datos en el destino no se copian al volumen si el volumen está vacío. Por defecto, el contenido en el destino de destino se copia en un volumen montado si está vacío. |

```console {title="Example"}
$ docker run -v myvolume:/data:ro
```

## Crear y gestionar volúmenes

A diferencia de un montaje de tipo bind, puedes crear y gestionar volúmenes fuera del ámbito de cualquier contenedor.

Crear un volumen:

```console
$ docker volume create my-vol
```

Listar volúmenes:

```console
$ docker volume ls

local               my-vol
```

Inspeccionar un volumen:

```console
$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
```

Eliminar un volumen:

```console
$ docker volume rm my-vol
```

## Iniciar un contenedor con un volumen

Si inicias un contenedor con un volumen que aún no existe, Docker crea el volumen por ti. El siguiente ejemplo monta el volumen `myvol2` en `/app/` en el contenedor.

Los siguientes ejemplos de `-v` y `--mount` producen el mismo resultado. No puedes ejecutarlos ambos a menos que elimines el contenedor `devtest` y el volumen `myvol2` después de ejecutar el primero.

**`--mount`**



```console
$ docker run -d \
  --name devtest \
  --mount source=myvol2,target=/app \
  nginx:latest
```

**`-v`**



```console
$ docker run -d \
  --name devtest \
  -v myvol2:/app \
  nginx:latest
```



Utiliza `docker inspect devtest` para verificar que Docker haya creado el volumen y lo haya montado correctamente. Busca la sección `Mounts`:

```json
"Mounts": [
    {
        "Type": "volume",
        "Name": "myvol2",
        "Source": "/var/lib/docker/volumes/myvol2/_data",
        "Destination": "/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],
```

Esto muestra que el montaje es un volumen, muestra el origen y destino correctos, y que el montaje es de lectura-escritura.

Detén el contenedor y elimina el volumen. Ten en cuenta que la eliminación del volumen es un paso independiente.

```console
$ docker container stop devtest

$ docker container rm devtest

$ docker volume rm myvol2
```

## Usar un volumen con Docker Compose

El siguiente ejemplo muestra un único servicio de Docker Compose con un volumen:

```yaml
services:
  frontend:
    image: node:lts
    volumes:
      - myapp:/home/node/app
volumes:
  myapp:
```

Ejecutar `docker compose up` por primera vez crea un volumen. Docker reutiliza el mismo volumen cuando ejecutas el comando posteriormente.

Puedes crear un volumen directamente fuera de Compose utilizando `docker volume create` y luego hacer referencia a él dentro de `compose.yaml` de la siguiente manera:

```yaml
services:
  frontend:
    image: node:lts
    volumes:
      - myapp:/home/node/app
volumes:
  myapp:
    external: true
```

Para obtener más información sobre el uso de volúmenes con Compose, consulta la sección de [Volúmenes](/reference/compose-file/volumes/) en la especificación de Compose.

### Iniciar un servicio con volúmenes

Cuando inicias un servicio y defines un volumen, cada contenedor del servicio utiliza su propio volumen local. Ninguno de los contenedores puede compartir estos datos si utilizas el controlador de volumen `local`. Sin embargo, algunos controladores de volumen admiten almacenamiento compartido.

El siguiente ejemplo inicia un servicio `nginx` con cuatro réplicas, cada una de las cuales utiliza un volumen local llamado `myvol2`.

```console
$ docker service create -d \
  --replicas=4 \
  --name devtest-service \
  --mount source=myvol2,target=/app \
  nginx:latest
```

Utiliza `docker service ps devtest-service` para verificar que el servicio se está ejecutando:

```console
$ docker service ps devtest-service

ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
4d7oz1j85wwn        devtest-service.1   nginx:latest        moby                Running             Running 14 seconds ago
```

Puedes eliminar el servicio para detener las tareas en ejecución:

```console
$ docker service rm devtest-service
```

Eliminar el servicio no elimina los volúmenes creados por el mismo. La eliminación del volumen es un paso independiente.

### Precargar un volumen utilizando un contenedor

Si inicias un contenedor que crea un nuevo volumen, y el contenedor tiene archivos o directorios en el directorio que se va a montar, como `/app/`, Docker copia el contenido del directorio en el volumen. Luego, el contenedor monta y utiliza el volumen, y otros contenedores que utilicen el volumen también tendrán acceso al contenido precargado.

Para demostrar esto, el siguiente ejemplo inicia un contenedor `nginx` y precarga el nuevo volumen `nginx-vol` con el contenido del directorio `/usr/share/nginx/html` del contenedor. Aquí es donde Nginx stores su contenido HTML predeterminado.

Los ejemplos de `--mount` y `-v` tienen el mismo resultado final.

**`--mount`**



```console
$ docker run -d \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html \
  nginx:latest
```

**`-v`**



```console
$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html \
  nginx:latest
```



Después de ejecutar cualquiera de estos ejemplos, ejecuta los siguientes comandos para limpiar los contenedores y volúmenes. Ten en cuenta que la eliminación de volúmenes es un paso independiente.

```console
$ docker container stop nginxtest

$ docker container rm nginxtest

$ docker volume rm nginx-vol
```

## Usar un volumen de solo lectura

Para algunas aplicaciones de desarrollo, el contenedor necesita escribir en el montaje de tipo bind de modo que los cambios se propaguen de vuelta al anfitrión de Docker. En otras ocasiones, el contenedor solo necesita acceso de lectura a los datos. Múltiples contenedores pueden montar el mismo volumen. Puedes montar simultáneamente un único volumen como `read-write` (lectura-escritura) para algunos contenedores y como `read-only` (solo lectura) para otros.

El siguiente ejemplo modifica el anterior. Monta el directorio como un volumen de solo lectura, añadiendo `ro` a la lista de opciones (vacía por defecto), después del punto de montaje dentro del contenedor. Cuando hay varias opciones presentes, puedes separarlas utilizando comas.

Los ejemplos de `--mount` y `-v` tienen el mismo resultado.

**`--mount`**



```console
$ docker run -d \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
  nginx:latest
```

**`-v`**



```console
$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest
```



Utiliza `docker inspect nginxtest` para verificar que Docker haya creado el montaje de solo lectura correctamente. Busca la sección `Mounts`:

```json
"Mounts": [
    {
        "Type": "volume",
        "Name": "nginx-vol",
        "Source": "/var/lib/docker/volumes/nginx-vol/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": false,
        "Propagation": ""
    }
],
```

Detén y elimina el contenedor, y elimina el volumen. La eliminación del volumen es un paso independiente.

```console
$ docker container stop nginxtest

$ docker container rm nginxtest

$ docker volume rm nginx-vol
```

## Montar un subdirectorio de volumen

Al montar un volumen en un contenedor, puedes especificar un subdirectorio del volumen que desees utilizar con el parámetro `volume-subpath` de la bandera `--mount`. El subdirectorio que especifiques debe existir en el volumen antes de intentar montarlo en un contenedor; si no existe, el montaje fallará.

Especificar `volume-subpath` es útil si solo deseas compartir una parte específica de un volumen con un contenedor. Por ejemplo, supón que tienes múltiples contenedores ejecutándose y deseas almacenar los registros (logs) de cada contenedor en un volumen compartido. Puedes crear un subdirectorio para cada contenedor en el volumen compartido y montar dicho subdirectorio en el contenedor.

El siguiente ejemplo crea un volumen `logs` e inicia los subdirectorios `app1` y `app2` en el volumen. Luego, inicia dos contenedores y monta uno de los subdirectorios del volumen `logs` en cada contenedor. Este ejemplo asume que los procesos de los contenedores escriben sus registros en `/var/log/app1` y `/var/log/app2`.

```console
$ docker volume create logs
$ docker run --rm \
  --mount src=logs,dst=/logs \
  alpine mkdir -p /logs/app1 /logs/app2
$ docker run -d \
  --name=app1 \
  --mount src=logs,dst=/var/log/app1,volume-subpath=app1 \
  app1:latest
$ docker run -d \
  --name=app2 \
  --mount src=logs,dst=/var/log/app2,volume-subpath=app2 \
  app2:latest
```

Con esta configuración, los contenedores escriben sus registros en subdirectorios separados del volumen `logs`. Los contenedores no pueden acceder a los registros del otro contenedor.

## Compartir datos entre máquinas

Al construir aplicaciones tolerantes a fallos, es posible que necesites configurar múltiples réplicas del mismo servicio para que tengan acceso a los mismos archivos.

![shared storage](/engine/storage/volumes/images/volumes-shared-storage.webp)

Existen varias formas de lograr esto al desarrollar tus aplicaciones. Una es añadir lógica a tu aplicación para almacenar archivos en un sistema de almacenamiento de objetos en la nube como Amazon S3. Otra es crear volúmenes con un controlador que admita la escritura de archivos en un sistema de almacenamiento externo como NFS o Amazon S3.

Los controladores de volumen te permiten abstraer el sistema de almacenamiento subyacente de la lógica de la aplicación. Por ejemplo, si tus servicios utilizan un volumen con un controlador NFS, puedes actualizar los servicios para utilizar un controlador diferente (por ejemplo, para almacenar datos en la nube) sin cambiar la lógica de la aplicación.

## Usar un controlador de volumen

Cuando creas un volumen utilizando `docker volume create`, o cuando inicias un contenedor que utiliza un volumen que aún no se ha creado, puedes especificar un controlador de volumen. Los siguientes ejemplos utilizan el controlador de volumen `rclone/docker-volume-rclone`, primero al crear un volumen independiente y luego al iniciar un contenedor que crea un nuevo volumen.

> [!NOTE]
>
> Si tu controlador de volumen acepta una lista separada por comas como opción, debes escapar el valor del analizador CSV externo. Para escapar un `volume-opt`, rodéalo con comillas dobles (`"`) y rodea todo el parámetro de montaje con comillas simples (`'`).
>
> Por ejemplo, el controlador `local` acepta opciones de montaje como una lista separada por comas en el parámetro `o`. Este ejemplo muestra la forma correcta de escapar la lista.
>
> ```console
> $ docker service create \
>  --mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"' \
>  --name myservice \
>  <IMAGE>
> ```

### Configuración inicial

El siguiente ejemplo asume que tienes dos nodos, el primero de los cuales es un anfitrión de Docker y puede conectarse al segundo nodo utilizando SSH.

En el anfitrión de Docker, instala el complemento `rclone/docker-volume-rclone`:

```console
$ docker plugin install --grant-all-permissions rclone/docker-volume-rclone --aliases rclone
```

### Crear un volumen utilizando un controlador de volumen

Este ejemplo monta el directorio `/remote` del anfitrión `1.2.3.4` en un volumen llamado `rclonevolume`. Cada controlador de volumen puede tener cero o más opciones configurables; cada una de ellas se especifica utilizando una bandera `-o`.

```console
$ docker volume create \
  -d rclone \
  --name rclonevolume \
  -o type=sftp \
  -o path=remote \
  -o sftp-host=1.2.3.4 \
  -o sftp-user=user \
  -o "sftp-password=$(cat file_containing_password_for_remote_host)"
```

Este volumen ahora se puede montar en contenedores.

### Iniciar un contenedor que crea un volumen utilizando un controlador de volumen

> [!NOTE]
>
> Si el controlador de volumen requiere que pases alguna opción, debes utilizar la bandera `--mount` para montar el volumen y no `-v`.

```console
$ docker run -d \
  --name rclone-container \
  --mount type=volume,volume-driver=rclone,src=rclonevolume,target=/app,volume-opt=type=sftp,volume-opt=path=remote,volume-opt=sftp-host=1.2.3.4,volume-opt=sftp-user=user,volume-opt=-o "sftp-password=$(cat file_containing_password_for_remote_host)" \
  nginx:latest
```

### Crear un servicio que crea un volumen NFS

El siguiente ejemplo muestra cómo se puede crear un volumen NFS al crear un servicio. Utiliza `10.0.0.10` como servidor NFS y `/var/docker-nfs` como el directorio exportado en el servidor NFS. Ten en cuenta que el controlador de volumen especificado es `local`.

#### NFSv3

```console
$ docker service create -d \
  --name nfs-service \
  --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,volume-opt=o=addr=10.0.0.10' \
  nginx:latest
```

#### NFSv4

```console
$ docker service create -d \
    --name nfs-service \
    --mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,"volume-opt=o=addr=10.0.0.10,rw,nfsvers=4,async"' \
    nginx:latest
```

### Crear volúmenes CIFS/Samba

Puedes montar un recurso compartido de Samba directamente en Docker sin configurar un punto de montaje en tu anfitrión.

```console
$ docker volume create \
	--driver local \
	--opt type=cifs \
	--opt device=//uxxxxx.your-server.de/backup \
	--opt o=addr=uxxxxx.your-server.de,username=uxxxxxxx,password=*****,file_mode=0777,dir_mode=0777 \
	--name cifs-volume
```

La opción `addr` es necesaria si especificas un nombre de anfitrión en lugar de una IP. Esto permite que Docker realice la búsqueda del nombre de anfitrión.

### Dispositivos de almacenamiento de bloques

Puedes montar un dispositivo de almacenamiento de bloques, como una unidad externa o una partición de disco, en un contenedor. El siguiente ejemplo muestra cómo crear y utilizar un archivo como un dispositivo de almacenamiento de bloques, y cómo montar el dispositivo de bloques como un volumen de contenedor.

> [!IMPORTANT]
>
> El siguiente procedimiento es únicamente un ejemplo. La solución ilustrada aquí no se recomienda como práctica general. No intentes este enfoque a menos que estés seguro de lo que estás haciendo.

#### Cómo funciona el montaje de dispositivos de bloques

Internamente, la bandera `--mount` utilizando el controlador de almacenamiento `local` invoca la llamada al sistema `mount` de Linux y reenvía las opciones que le pasas sin modificarlas. Docker no implementa ninguna funcionalidad adicional sobre las características nativas de montaje admitidas por el kernel de Linux.

Si estás familiarizado con el [comando `mount` de Linux](https://man7.org/linux/man-pages/man8/mount.8.html), puedes pensar en las opciones de `--mount` como si se reenviaran al comando `mount` de la siguiente manera:

```console
$ mount -t <mount.volume-opt.type> <mount.volume-opt.device> <mount.dst> -o <mount.volume-opts.o>
```

Para explicar esto más detalladamente, considera el siguiente ejemplo del comando `mount`. Este comando monta el dispositivo `/dev/loop5` en la ruta `/external-drive` del sistema.

```console
$ mount -t ext4 /dev/loop5 /external-drive
```

El siguiente comando `docker run` logra un resultado similar, desde el punto de vista del contenedor que se está ejecutando. Ejecutar un contenedor con esta opción `--mount` configura el montaje de la misma manera que si hubieras ejecutado el comando `mount` del ejemplo anterior.

```console
$ docker run \
  --mount='type=volume,dst=/external-drive,volume-driver=local,volume-opt=device=/dev/loop5,volume-opt=type=ext4'
```

No puedes ejecutar el comando `mount` directamente dentro del contenedor porque este no puede acceder al dispositivo `/dev/loop5`. Por eso el comando `docker run` utiliza la opción `--mount`.

#### Ejemplo: Montar un dispositivo de bloques en un contenedor

Los siguientes pasos crean un sistema de archivos `ext4` y lo montan en un contenedor. La compatibilidad del sistema de archivos depende de la versión del kernel de Linux que estés utilizando.

1. Crea un archivo y asígnale algo de espacio:

   ```console
   $ fallocate -l 1G disk.raw
   ```

2. Construye un sistema de archivos en el archivo `disk.raw`:

   ```console
   $ mkfs.ext4 disk.raw
   ```

3. Crea un dispositivo loop:

   ```console
   $ losetup -f --show disk.raw
   /dev/loop5
   ```

   > [!NOTE]
   >
   > `losetup` crea un dispositivo loop efímero que se elimina después del reinicio del sistema, o se puede eliminar manualmente con `losetup -d`.

4. Ejecuta un contenedor que monte el dispositivo loop como un volumen:

   ```console
   $ docker run -it --rm \
     --mount='type=volume,dst=/external-drive,volume-driver=local,volume-opt=device=/dev/loop5,volume-opt=type=ext4' \
     ubuntu bash
   ```

   Cuando el contenedor se inicia, la ruta `/external-drive` monta el archivo `disk.raw` del sistema de archivos del anfitrión como un dispositivo de bloques.

5. Cuando hayas terminado y el dispositivo se haya desmontado del contenedor, desconecta el dispositivo loop para eliminarlo del sistema anfitrión:

   ```console
   $ losetup -d /dev/loop5
   ```

## Respaldar, restaurar o migrar volúmenes de datos

Los volúmenes son útiles para realizar copias de seguridad, restauraciones y migraciones. Utiliza la bandera `--volumes-from` para crear un nuevo contenedor que monte ese volumen.

### Respaldar un volumen

Por ejemplo, crea un nuevo contenedor llamado `dbstore`:

```console
$ docker run -v /dbdata --name dbstore ubuntu /bin/bash
```

En el siguiente comando:

- Inicia un nuevo contenedor y monta el volumen desde el contenedor `dbstore`
- Monta un directorio local del anfitrión como `/backup`
- Pasa un comando que empaquete (tar) el contenido del volumen `dbdata` en un archivo `backup.tar` dentro del directorio `/backup`.

```console
$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
```

Cuando el comando se completa y el contenedor se detiene, crea una copia de seguridad del volumen `dbdata`.

### Restaurar un volumen desde una copia de seguridad

Con la copia de seguridad recién creada, puedes restaurarla en el mismo contenedor o en otro contenedor que hayas creado en cualquier otro lugar.

Por ejemplo, crea un nuevo contenedor llamado `dbstore2`:

```console
$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
```

Luego, desempaqueta el archivo de copia de seguridad en el volumen de datos del nuevo contenedor:

```console
$ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
```

Puedes utilizar estas técnicas para automatizar las pruebas de copia de seguridad, migración y restauración utilizando tus herramientas preferidas.

## Eliminar volúmenes

Un volumen de datos de Docker persiste después de eliminar un contenedor. Hay dos tipos de volúmenes a considerar:

- Los volúmenes con nombre tienen un nombre específico, por ejemplo, `awesome:/bar`, donde `awesome` es el nombre.
- Los volúmenes anónimos no tienen un nombre específico. Por lo tanto, cuando se elimina el contenedor, puedes indicar al demonio de Docker Engine que los elimine.

### Eliminar volúmenes anónimos

Para eliminar automáticamente los volúmenes anónimos, utiliza la opción `--rm`. Por ejemplo, este comando crea un volumen `/foo` anónimo. Cuando eliminas el contenedor, Docker Engine elimina el volumen `/foo` pero no el volumen `awesome`.

La opción `--rm` funciona tanto con contenedores en primer plano como en segundo plano (`-d`). Los volúmenes anónimos se limpian cuando el contenedor finaliza.

```console
$ docker run --rm -v /foo -v awesome:/bar busybox top
```

> [!NOTE]
>
> Si otro contenedor vincula los volúmenes con `--volumes-from`, las definiciones de volumen se _copian_ y el volumen anónimo también permanece después de que se elimina el primer contenedor.

### Eliminar todos los volúmenes

Para eliminar todos los volúmenes no utilizados y liberar espacio:

```console
$ docker volume prune
```

## Siguientes pasos

- Aprende sobre los [montajes de tipo bind](/engine/storage/volumes/bind-mounts/).
- Aprende sobre los [montajes tmpfs](/engine/storage/volumes/tmpfs/).
- Aprende sobre los [controladores de almacenamiento](/engine/storage/drivers/).
- Aprende sobre los [complementos de controladores de volumen de terceros](/engine/extend/legacy_plugins/).

