Administrando los Sistemas de Archivos de los Contenedores

DockerDockerBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Por defecto, todos los archivos creados dentro de un contenedor se almacenan en una capa de contenedor escribible. Eso significa que:

  • Si el contenedor ya no existe, los datos se pierden.
  • La capa escribible del contenedor está estrechamente acoplada a la máquina host.
  • Para administrar el sistema de archivos, se necesita un controlador de almacenamiento que proporcione un sistema de archivos union, utilizando el kernel de Linux. Esta abstracción adicional reduce el rendimiento en comparación con los volúmenes de datos, que escriben directamente en el sistema de archivos.

Docker ofrece dos opciones para almacenar archivos en la máquina host: volúmenes y montajes vinculados. Si estás ejecutando Docker en Linux, también puedes usar un montaje tmpfs, y con Docker en Windows también puedes usar un tuberia con nombre.

Tipos de Montajes
  • Los volúmenes se almacenan en el sistema de archivos host administrado por Docker.
  • Los montajes vinculados se almacenan en cualquier lugar del sistema host.
  • Los montajes tmpfs se almacenan solo en la memoria host.

Originalmente, la bandera --mount se utilizaba para los servicios de Docker Swarm y la bandera --volume se utilizaba para contenedores independientes. A partir de Docker 17.06 y versiones superiores, también puedes usar --mount para contenedores independientes y, en general, es más explícito y detallado que --volume.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/VolumeOperationsGroup(["Volume Operations"]) docker(("Docker")) -.-> docker/SystemManagementGroup(["System Management"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/rm("Remove Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/VolumeOperationsGroup -.-> docker/volume("Manage Volumes") docker/SystemManagementGroup -.-> docker/prune("Remove Unused Docker Objects") subgraph Lab Skills docker/run -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/stop -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/rm -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/exec -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/inspect -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/volume -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} docker/prune -.-> lab-148984{{"Administrando los Sistemas de Archivos de los Contenedores"}} end

Volúmenes

Un volumen de datos o volumen es un directorio que omite el Sistema de Archivos Union de Docker.

Hay tres tipos de volúmenes:

  • volumen anónimo,
  • volumen nombrado, y
  • volumen host.

Volumen Anónimo

Vamos a crear una instancia de una popular base de datos NoSQL de código abierto llamada CouchDB y usar un volumen anónimo para almacenar los archivos de datos de la base de datos.

Para ejecutar una instancia de CouchDB, use la imagen de CouchDB de Docker Hub en https://hub.docker.com/_/couchdb. La documentación dice que el predeterminado para CouchDB es escribir los archivos de la base de datos en el disco del sistema host usando su propio sistema de gestión de volúmenes interno.

Ejecute el siguiente comando:

docker run -d -p 5984:5984 --name my-couchdb -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

CouchDB creará un volumen anónimo y generará un nombre hash. Verifique los volúmenes en su sistema host:

labex:~/ $ docker volume ls
DRIVER VOLUME NAME
local 1d292aca855adb9de9be7acea88f6d3f8e6a08eef5bfd986a81f073f1906b82f

Establezca una variable de entorno VOLUME con el valor del nombre generado:

export VOLUME=<VOLUME NAME>

Y examine el volumen que se creó, use el nombre hash que se generó para el volumen:

$ docker volume inspect $VOLUME
[
{
  "CreatedAt": "2020-09-24T14:10:07Z",
  "Driver": "local",
  "Labels": null,
  "Mountpoint": "/var/lib/docker/volumes/f543c5319ebd96b7701dc1f2d915f21b095dfb35adbb8dc851630e098d526a50/_data",
  "Name": "f543c5319ebd96b7701dc1f2d915f21b095dfb35adbb8dc851630e098d526a50",
  "Options": null,
  "Scope": "local"
}
]

Vea que Docker ha creado y gestiona un volumen en el sistema de archivos del host de Docker en /var/lib/docker/volumes/$VOLUME_NAME/_data. Tenga en cuenta que este no es un camino en la máquina host, sino una parte del sistema de archivos administrado por Docker.

Cree una nueva base de datos mydb e inserte un nuevo documento con un mensaje hello world.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1 -d '{"msg": "hello world"}'

Detenga el contenedor y vuelva a iniciarlo:

docker stop my-couchdb
docker start my-couchdb

Recupere el documento de la base de datos para probar que los datos se persistieron.

curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/_all_docs
curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1

Salida:

## $ curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/_all_docs
{"total_rows":1,"offset":0,"rows":[
{"id":"1","key":"1","value":{"rev":"1-c09289617e06b96bc747fb1201fea7f1"}}
]}

## $ curl -X GET -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1
{"_id":"1","_rev":"1-c09289617e06b96bc747fb1201fea7f1","msg":"hello world"}

Compartir Volúmenes

Puede compartir un volumen anónimo con otro contenedor usando la opción --volumes-from.

Cree un contenedor busybox con un volumen anónimo montado en un directorio /data en el contenedor y, usando comandos de shell, escriba un mensaje en un archivo de registro.

$ docker run -it --name busybox1 -v /data busybox sh
/ ## echo "hello from busybox1" > /data/hi.log
/ ## ls /data
hi.log
/ ## exit

Asegúrese de que el contenedor busybox1 esté detenido pero no eliminado.

labex:~/ $ docker ps -a | grep busybox1
f4dbf9ee7513   busybox                               "sh"                     2 minutes ago   Exited (0) About a minute ago                                                                                                                                          busybox1

Luego cree un segundo contenedor busybox llamado busybox2 usando la opción --volumes-from para compartir el volumen creado por busybox1:

$ docker run --rm -it --name busybox2 --volumes-from busybox1 busybox sh
/ ## ls -al /data
total 12
drwxr-xr-x 2 root root 4096 Jan 23 07:20.
drwxr-xr-x 1 root root 4096 Jan 23 07:24..
-rw-r--r-- 1 root root 20 Jan 23 07:20 hi.log
/ ## cat /data/hi.log
hello from busybox1
/ ## exit

Docker creó el volumen anónimo que pudo compartir usando la opción --volumes-from y creó un nuevo volumen anónimo.

labex:~/ $ docker volume ls
DRIVER VOLUME NAME
local 0f971b2477d5fc0d0c2b31fc908ee59d6b577b4887e381964650ce6853890dc9
local 1d292aca855adb9de9be7acea88f6d3f8e6a08eef5bfd986a81f073f1906b82f

Limpie los volúmenes y contenedores existentes.

docker stop my-couchdb
docker rm my-couchdb
docker rm busybox1
docker volume rm $(docker volume ls -q)
docker system prune -a
clear

Volumen nombrado

Un volumen nombrado y un volumen anónimo son similares en que Docker gestiona donde se encuentran. Sin embargo, un volumen nombrado se puede referenciar por nombre al montarlo en un directorio de contenedor. Esto es útil si desea compartir un volumen entre múltiples contenedores.

Primero, cree un volumen nombrado:

docker volume create my-couchdb-data-volume

Verifique que el volumen se haya creado:

$ docker volume ls
DRIVER VOLUME NAME
local my-couchdb-data-volume

Ahora cree el contenedor de CouchDB llamado my-couchdb-name-vol usando el volumen nombrado:

docker run -d -p 59840:5984 --name my-couchdb-name-vol -v my-couchdb-data-volume:/opt/couchdb/data -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

Espere a que el contenedor de CouchDB se esté ejecutando y la instancia esté disponible.

Cree una nueva base de datos mydb e inserte un nuevo documento con un mensaje hello world.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:59840/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:59840/mydb/1 -d '{"msg": "hello world"}'

Ahora es fácil compartir el volumen con otro contenedor. Por ejemplo, lea el contenido del volumen usando la imagen busybox y comparta el volumen my-couchdb-data-volume montando el volumen en un directorio en el contenedor busybox.

labex:~/ $ docker run --rm -it --name busybox -v my-couchdb-data-volume:/myvolume busybox sh
/ #
/ ## ls -al /myvolume
total 40
drwxr-xr-x 4 5984 5984 4096 Jan 23 07:30.
drwxr-xr-x 1 root root 4096 Jan 23 07:31..
drwxr-xr-x 2 5984 5984 4096 Jan 23 07:29.delete
-rw-r--r-- 1 5984 5984 8388 Jan 23 07:30 _dbs.couch
-rw-r--r-- 1 5984 5984 8385 Jan 23 07:29 _nodes.couch
drwxr-xr-x 4 5984 5984 4096 Jan 23 07:30 shards
/ ## exit

Puede verificar el sistema de archivos administrado por Docker para volúmenes ejecutando un contenedor busybox con permisos privilegiados y estableciendo el identificador de proceso en host para inspeccionar el sistema host y navegar a los directorios administrados por Docker.

docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh
/ ## ls -l /var/lib/docker/volumes
total 28
-rw------- 1 root root 32768 Nov 10 15:54 metadata.db
drwxr-xr-x 3 root root 4096 Nov 10 15:54 my-couchdb-data-volume
/ ## exit

Limpie:

docker stop my-couchdb
docker rm my-couchdb
docker volume rm my-couchdb-data-volume
docker system prune -a
docker volume prune
clear

Volumen Host

Cuando desea acceder fácilmente al directorio de volumen desde la máquina host directamente en lugar de usar los directorios administrados por Docker, puede crear un volumen host.

Usemos un directorio en el directorio de trabajo actual (indicado con el comando pwd) llamado data, o elija su propio directorio de datos en la máquina host, por ejemplo, /home/couchdb/data. Permitimos que Docker cree el directorio $(pwd)/data si aún no existe. Montamos el volumen host dentro del contenedor de CouchDB en el directorio de contenedor /opt/couchdb/data, que es el directorio de datos predeterminado para CouchDB.

Ejecute el siguiente comando:

cd /home/labex/project
docker run -d -p 5984:5984 --name my-couchdb -v $(pwd)/data:/opt/couchdb/data -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=passw0rd1 couchdb:3.1

Verifique que se haya creado un directorio data:

$ ls -al
total 20
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14.
drwxr-x--- 25 labex labex 4096 Aug 29 14:14..
drwxr-xr-x 3 5984 5984 4096 Aug 29 14:14 data

y que CouchDB ha creado archivos de datos aquí:

$ ls -al data
total 32
drwxr-xr-x 3 5984 5984 4096 Aug 29 14:14.
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14..
-rw-r--r-- 1 5984 5984 4257 Aug 29 14:14 _dbs.couch
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:14.delete
-rw-r--r-- 1 5984 5984 8385 Aug 29 14:14 _nodes.couch

También verifique que ahora Docker no ha creado ningún volumen administrado, porque ahora estamos usando un volumen host.

docker volume ls

y

docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh
sh-5.1## ls -l /var/lib/docker/volumes
total 28
brw------- 1 root root 252, 3 Jan 23 15:15 backingFsBlockDev
-rw------- 1 root root 32768 Jan 23 15:33 metadata.db
drwx-----x 3 root root 4096 Jan 23 15:26 my-couchdb-data-volume
sh-5.1## exit

Cree una nueva base de datos mydb e inserte un nuevo documento con un mensaje hello world.

curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb
curl -X PUT -u admin:passw0rd1 http://127.0.0.1:5984/mydb/1 -d '{"msg": "hello world"}'

Tenga en cuenta que CouchDB creó una carpeta shards:

$ ls -al data
total 40
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15.
drwxrwxr-x 3 labex labex 4096 Aug 29 14:14..
-rw-r--r-- 1 5984 5984 8388 Aug 29 14:15 _dbs.couch
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:14.delete
-rw-r--r-- 1 5984 5984 8385 Aug 29 14:14 _nodes.couch
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15 shards

Liste el contenido del directorio shards:

$ ls -al data/shards
total 16
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15.
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15..
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15 00000000-7fffffff
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15 80000000-ffffffff

y el primer fragmento:

$ ls -al data/shards/00000000-7fffffff/
total 20
drwxr-xr-x 2 5984 5984 4096 Aug 29 14:15.
drwxr-xr-x 4 5984 5984 4096 Aug 29 14:15..
-rw-r--r-- 1 5984 5984 8346 Aug 29 14:15 mydb.1693289721.couch

Un fragmento es una partición horizontal de datos en una base de datos. Particionar los datos en fragmentos y distribuir copias de cada fragmento a diferentes nodos en un clúster le da a los datos una mayor durabilidad frente a la pérdida de nodos. CouchDB particiona automáticamente las bases de datos y distribuye los subconjuntos de documentos entre los nodos.

Limpie:

docker stop my-couchdb
docker rm my-couchdb
sudo rm -rf $(pwd)/data
docker system prune -a

Montajes Vinculados

La sintaxis mount es recomendada por Docker en lugar de la sintaxis volume. Los montajes vinculados tienen una funcionalidad limitada en comparación con los volúmenes. Un archivo o directorio se referencia por su ruta completa en la máquina host cuando se monta en un contenedor. Los montajes vinculados dependen de que el sistema de archivos de la máquina host tenga una estructura de directorio específica disponible y no se puede usar la CLI de Docker para administrar los montajes vinculados. Tenga en cuenta que los montajes vinculados pueden cambiar el sistema de archivos host a través de procesos que se ejecutan en un contenedor.

En lugar de usar la sintaxis -v con tres campos separados por el separador de dos puntos (:), la sintaxis mount es más detallada y utiliza múltiples pares clave-valor:

  • type: bind, volume o tmpfs,
  • source: ruta al archivo o directorio en la máquina host,
  • destination: ruta en el contenedor,
  • readonly,
  • bind-propagation: rprivate, private, rshared, shared, rslave, slave,
  • consistency: consistent, delegated, cached,
  • mount.
cd /home/labex/project
mkdir data
docker run -it --name busybox --mount type=bind,source="$(pwd)"/data,target=/data busybox sh

Escriba el comando en el contenedor:

echo "hello busybox" > /data/hi.txt
exit

Verifique que el archivo se haya creado en la máquina host.

cat data/hi.txt

[Opcional] OverlayFS

OverlayFS es una implementación de sistema de archivos de montaje union para Linux. Para entender qué es un volumen de Docker, ayuda entender cómo funcionan las capas y el sistema de archivos en Docker.

Para iniciar un contenedor, Docker toma la imagen de solo lectura y crea una nueva capa de lectura-escritura encima. Para ver las capas como una sola, Docker utiliza un Sistema de Archivos Union o OverlayFS (Sistema de Archivos Superpuesto), específicamente el controlador de almacenamiento overlay2.

Para ver los archivos administrados por el host de Docker, necesita acceder al sistema de archivos del proceso de Docker. Usando las banderas --privileged y --pid=host puede acceder al espacio de nombres de identificadores de proceso del host desde dentro de un contenedor como busybox. Luego puede navegar al directorio /var/lib/docker/overlay2 de Docker para ver las capas descargadas que son administradas por Docker.

Para ver la lista actual de capas en Docker:

$ docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh

/ ## ls -l /var/lib/docker/overlay2
total 16
drwx------ 3 root root 4096 Sep 25 19:44 0e55ecaa4d17c353191e68022d9a17fde64fb5e9217b07b5c56eb4c74dad5b32
drwx------ 5 root root 4096 Sep 25 19:44 187854d05ccd18980642e820b0d2be6a127ba85d8ed96315bb5ae37eb1add36d
drwx------ 4 root root 4096 Sep 25 19:44 187854d05ccd18980642e820b0d2be6a127ba85d8ed96315bb5ae37eb1add36d-init
drwx------ 2 root root 4096 Sep 25 19:44 l

/ ## exit

Descargue la imagen ubuntu y verifique nuevamente:

docker pull ubuntu
docker run -it --privileged --pid=host busybox nsenter -t 1 -m -u -n -i sh

Escriba el comando para ver la lista de capas nuevamente:

ls -l /var/lib/docker/overlay2/ & exit

Verá que al descargar la imagen ubuntu, se descargaron implícitamente 4 nuevas capas:

  • a611792b4cac502995fa88a888261dfba0b5d852e72f9db9e075050991423779
  • d181f1a41fc35a45c16e8bfcb8eee6f768f3b98f82210a43ea65f284a45fcd65
  • dac2f37f6280a076836d39b87b0ae5ebf5c0d386b6d8b991b103aadbcebaa7c6
  • f3e921b440c37c86d06cd9c9fb70df50edad553c36cc87f84d5eeba734aae709

El controlador de almacenamiento overlay2 esencialmente superpone diferentes directorios en el host y los presenta como un solo directorio.

  • capa base o lowerdir,
  • capa diff o upperdir,
  • capa superpuesta (vista del usuario), y
  • directorio work.

OverlayFS se refiere a los directorios inferiores como lowerdir, que contiene la imagen base y las capas de solo lectura (R/O) que se descargan.

El directorio superior se llama upperdir y es la capa de contenedor de lectura-escritura (R/W).

La vista unificada o capa overlay se llama merged.

Finalmente, un workdir es obligatorio, que es un directorio vacío utilizado por overlay para su uso interno.

El controlador overlay2 admite hasta 128 capas inferiores de OverlayFS. El directorio l contiene identificadores de capa acortados como enlaces simbólicos.

Controlador de almacenamiento Overlay2

Limpie:

docker system prune -a
clear

Resumen

En este laboratorio, aprendiste cómo administrar datos en contenedores usando volúmenes y montajes vinculados. También aprendiste sobre el controlador de almacenamiento overlay2 y cómo utiliza el sistema de archivos union para administrar las capas.