En el apartado sobre Dockerfile vimos un ejemplo práctico sobre cómo crear volúmenes. Estos nos permitían hacer persistente la información una vez que el contenedor era parado o destruido. Pues bien, la idea de esta entrada es profundizar en el almacenamiento en Docker.
Algunos conceptos
Ya sabemos que tanto las imágenes como los contenedores se almacenan directamente en el disco. Docker posee una arquitectura de almacenamiento flexible que permite elegir entre diversos controladores (“drivers”) dependiendo del sistema operativo y del entorno. Cada uno de los controladores se basa en el sistema de ficheros o bien en volúmenes LVM.
Cada controlador gestiona los datos de manera diferente. Esto hace que contenedores e imágenes con diferentes controladores no sean compatibles entre sí. Esto es, si creamos una imagen con un controlador y finalmente decidimos utilizar otro, este último no será accesible.
Un resumen:
Hay que tener en cuenta que, dependiendo del sistema operativo que utilicemos y su versión de Docker, escogerá por defecto el controlador más óptimo y estable. Lo podemos comprobar mediante el comando:
#docker info Server Version: 17.09.1-ce Storage Driver: overlay Backing Filesystem: extfs Supports d_type: true
Podemos utilizar un módulo distinto. Para ello debemos configurar el servicio utilizando la opción “—storage-driver=driver”.
Device Mapper
Vamos a echar un vistazo al driver “Device Mapper”, típico de Red Hat y otros sistemas populares. Cuando se utiliza, cada imagen y contenedor se alojan dentro de su propio dispositivo virtual; la gran diferencia es que funciona a nivel de bloque y a no nivel de fichero. Además, utiliza la técnica de instantánea (snapshot) para manipular imágenes y contenedores.
Al escoger este driver disponemos de dos opciones:
- Crear un dispositivo virtual llamado loop, que será un fichero alojado dentro de :
ls -l /var/lib/docker/devicemapper/devicemapper
- Emplear un disco físico (o partición) para utilizarlo como pool.
En este caso, el pool es un contenedor de imágenes y contenedores, además de sus instantáneas derivadas.
Las distribuciones que actualmente soportan ‘devicemapper’ serían:
-
- RHEL / Centos / Fedora / ScientificLinux
- Ubuntu
- Debian
Podemos consultar información al respecto con este documento.
Para ArchLinux el driver recomendado es “overlay2”. En sistemas OpenSuse y SLES el recomendado es “btrfs” Aunque ya hemos dicho que Ubuntu soporta “DeviceMapper” el recomendado para entornos de producción es “aufs3”
En la ubicación de los datos podemos diferenciar dónde se guardan el contenido de las imágenes y contenedores
/var/lib/docker/devicemapper/devicemapper/data
y dónde se guardan los metadatos
/var/lib/docker/devicemapper/devicemapper/metadata
En entornos de producción es recomendado utilizar un dispositivo separado para el uso de este driver. Antes de cambiar del modo ‘loop’ al modo ‘direct-lvm’, esto es, para utilizar dispositivos, es necesario utilizar una copia de seguridad de imágenes y contenedores, ya que el cambio de driver conlleva la pérdida de datos. Para ello utilizamos el comando “docker save” que ya vimos en un artículo anterior.
Laboratorio de pruebas
Vamos a ver un ejemplo de los contenedores. Utilizaremos las imágenes y contenedores que tengo en una máquina virtual con CentOS 7 en mi laptop. Para esta versión el driver por defecto es “overlay”. Para cambiarlo vamos a crear un fichero llamado /etc/docker/daemon.json. Empezamos por parar primero el servicio con:
systemctl stop docker
y ejecutamos:
vi /etc/docker/daemon.json #Añadimos: { "storage-driver": "devicemapper" } #Ya podemos encender el demonio. Si tenemos imágenes o contenedores utilizando ‘overlay’ debemos guardarlos en una copia de seguridad, ya que se perderán systemctl start docker
De esta manera indicamos que vamos a crear el contenedor con un volumen llamado “volumen1”. Una vez creado podemos verlo en la ubicación:
ls -la /var/lib/docker/devicemapper/mnt/ drwxr-xr-x 3 root root 30 feb 27 19:07 9dbeca5ff1a62881afdc3d30a304bd1ed25a39efc1c70e49e48946b7cd7aceb2
Otra manera es utilizar el siguiente comando:
[root@servdocker mnt]# docker volume ls DRIVER VOLUME NAME local cd74b0ffa2491a5b9c1b323c6c388db127076851e47f8b9b8be645da6b42312c
Gestión de volúmenes
Volumen se refiere a un directorio especial asignado a un contenedor. Este aloja los datos dentro del directorio
/var/lib/docker/volumes
Las principales ventajas de utilizar volúmenes son:
- Se inicializan durante la creación del contenedor.
- Las modificaciones realizadas van directamente a disco, sin pasar primero por caché.
- Los cambios en el volumen no se verán afectados en el caso de que se actualice la base del contenedor.
- Se puede compartir en diferentes contenedores.
Cuando creamos un contenedor y queremos indicar el volumen utilizamos el parámetro “-v o –volume” y el nombre del directorio. Un ejemplo:
docker run -dti --name pruebas4 -p 8480:8080 -v opttomcat:/opt d99cebf5d107 9e7206697b0e9fd06bd709c8dd559371e3163030abf57fc221c66acff6a5c9b3
Y así, al listar los volúmenes disponibles:
root@servdocker volumes]# docker volume ls local e115b6f2a23545618f6e25d9106592710654ce4a23c627c37a3336ded500d986 local opttomcat
Otra interesante opción es que podemos indicar que el volumen sea, por ejemplo, sólo de lectura o permitir la escritura. Un ejemplo sería:
docker run -dti --name pruebas5 -p 8580:8080 -v opttomcat2:/opt:ro d99cebf5d107
Os invito a investigar y ampliar vuestros conocimientos al respecto. Todavía no tengo decidido de que irá el siguiente capítulo. Si tenéis preferencia por algún tema específico relacionado con Docker lo podéis dejar en los comentarios. Nos vamos leyendo ^.^
Derechos de la imagen de portada Wikimedia con derechos Creative Commons.
Excelente articulo, no había encontrado información tan buena ni en ingles, me leeré todos tus artículos, Últimamente me hecho un fiel seguidor de docker, porque permite hacer cosas sin tener que batallar ni tardar tanto para configurar un ambiente, Últimamente para un proyecto de maestría me he tenido que armar un cluster MPI para programar en paralelo (se podria decir que lo que haría es Multicore simulando multinode), y pues lo primero que se me vino a la mente fue armarme un cluster virtual usando nodos de docker como si fueran nodos físicos, un problema es que quería simular como si fuera un ambiente real, y el problema es que cuando despliegas un contenedor docker por default puede usar todos los hilos de tus cpus lo cual en mi caso lo veo como un problema, y me tope con que es posible limitarle a los contenedores que cpus usar y… Leer más »