Volumenes
Los volumenes son almacenamientos persistentes ubicados en el sistema anfitrión a los cuales los contenedores tienen acceso. Son necesarios para prevenir la pérdida de los datos internos de los contenedores cada vez que éstos son borrados o recreados.
Algunos usos habituales:
- bases de datos;
- archivos de los usuarios;
- reportes de funcionamiento;
- etc.
Introducción
Las rutas internas de los contenedores están aisladas del sistema anfitrión. Asimismo los contenedores son incapaces de interactuar con los directorios y archivos del sistema anfitrión. host directamente.
El gestor de contenedores crea los volumenes en una ruta permitida del anfitrión. Luego crea un "punto de montaje" (una equivalencia) entre las rutas internas de los contenedores y las rutas internas de los volumenes.
---
title: "Volumenes - Idea general"
---
flowchart LR
subgraph proyecto [Entorno proyecto]
subgraph services [Servicios]
subgraph c1 ["`Contenedor 1`"]
r1["/ruta_1"]
r2["/ruta_2"]
end
subgraph c2 ["`Contenedor 2`"]
r3["/ruta_3"]
end
end
end
subgraph host [Host]
subgraph volumenes [Volumenes]
vol1["`Volumen 1
ruta_A`"]
vol2["`Volumen 2
ruta_B`"]
vol3["`Volumen 3
ruta_C`"]
end
end
vol1 o-.-o|montaje| r1
vol2 o-.-o|montaje| r2
vol3 o-.-o|montaje| r3
De esta manera los contenedores tienen acceso limitado al sistema de archivos del anfitrión a través de los volumenes. Si los contenedores son eliminados los volumenes y sus contenidos siguen existiendo y pueden ser reutilizados, migrados, etc.
Asignación de volumenes
El acceso de los contenedores
a los volumenes se indica
mediante el campo volumes
del archivo compose.yml
.
Un mismo proyecto permite definir múltiples volumenes;
además un mismo contenedor puede acceder
a varios volumenes simultáneamente.
Hay varias variantes de volumenes que pueden ser creados, las cuales se muestran a continuación.
Volumenes anónimos
Los volumenes anónimos se crean asignando un único valor que corresponde a la ruta interna del contenedor:
name: nombre_proyecto
services:
servicio_volumen:
build: .
# lista de rutas internas
volumes:
- ruta_contenedor
En este caso el programa gestor de los contenedores crea un volumen y le reserva al contenedor un directorio para guardar los datos persistentes.
Si el despliegue se realiza en sistemas GNU/Linux
entonces los voúmenes se suelen alojar en la ruta
/home/USUARIO/.local/share/containers/storage/volumes/
Al volumen anónimo se le asigna un nombre aleatorio de manera automática. Este tipo de volumenes es práctico para datos que no requieran ser transferidos ni preservados por mucho tiempo: cachés, algunos archivos de configuración, etc.
Volumenes con nombre
Los volumenes con nombre son similares a los volumenes anónimos. En este caso a cada ruta interna del contenedor se le asigna un nombre que funciona como un alias.
name: nombre_proyecto
services:
servicio_volumen:
build: .
# lista de volumenes accedidos
volumes:
# montajes (equivalencias)
- nombre_volumen:/root/logs
# lista de volumenes implementados
volumes:
nombre_volumen:
El nombre asignado al volumen
suele estar compuesto por el nombre del proyecto
y el alias definido para el volumen.
Por ejemplo en este caso
el volumen se llamaría
nombre_proyecto_alias_volumen
.
Este tipo de volumenes puede ser accedido
por múltiples contenedores mediante su alias.
Si el volumen requerido proviene de otro proyecto
entonces hace falta especificar el parámetro external
como true
:
# lista de volumenes implementados
volumes:
nombre_volumen:
external: true
name: nombre_completo_volumen
Los volumenes con nombre son una buena opción para datos que necesiten ser preservados y posiblemente transferidos a otras plataformas: bases de datos de producción, publicaciones de usuarios (ej: entradas de WordPress), etc. pero que no necesiten ser manipulados frecuentemente por desarrolladores ni administradores.
Volumenes de host
En este tipo de asignación no se crea un elemento de volumen sino que se monta una ruta del sistema anfitrión (el host) a la ruta de interés del contenedor.
services:
servicio_volumen:
build: .
# lista de volumenes accedidos
volumes:
# montajes (equivalencias)
- ruta_host:ruta_contenedor
# opciones de seguridad
security_opt:
- label=disable
Si la ruta indicada en el sistema host no existe entonces se creará automáticamente.
Este tipo de volumenes es práctico para darle un acceso inmediato de los archivos a desarrolladores y administradores del proyecto.
Read only
Los volumenes admiten el montaje
en el modo
de sólo lectura (read only).
Esto se realiza agregando :ro
detraś de los mapeos como se muestra:
Security Options
El atributo security_opt
es opcional en Docker
pero es indispensable en Podman
para otorgar y configurar los permisos de acceso
a los recursos del host
por parte del contenedor.
Haciendo label=disable
se libera el acceso al contenedor
de los recursos del usuario actual del sistema
pero no se da acceso a los recursos
que requieran permisos de administrador.
root
Usuario root
En los contenedores que corren imágenes basadas en Linux
el usuario predeterminado
es el usuario root
("raiz"),
que es el usuario administrador del sistema.
Su carpeta de usuario se encuentra
en la carpeta /root
,
en contraposición a los usuarios comunes,
que tienen sus archivos de usuario
dentro de la carpeta /home
.
Permisos de root
Docker hace funcionar a los contenedores
con plenos permisos de administrador.
Por este motivo
en Docker el usuario root
de cada contenedor
posee todos los permisos
de administrador por default.
Esto puede implicar un riesgo de seguridad,
la llamada "escalada de permisos",
si a los contenedores
se les da un acceso demasiado permisivo
a los recursos del sistema anfitrión.
Esto es diferente en Podman, el cual funciona en modo rootless (sin permisos de superusuario) por default y por tanto el usuario root de cada contenedor no tiene dichos permisos especiales a menos que se inicie Podman en modo rootful deliberadamente.
Ejemplo demo
En este demo se adapta la rutina del contador
pero en este caso los logs salen por consola
y por archivo en simultáneo.
El archivo es creado
con el nombre reporte.log
y los reportes son acumulativos.
demo contar
from time import sleep
from pathlib import Path
import sys
import logging
# ruta al reporte (en contenedor) : /root/logs/reporte.log
ruta_log = Path( "~/logs/reporte.log").expanduser()
logging.basicConfig(
level=logging.INFO, # mínimo nivel de log a publicar
format="%(asctime)s - %(levelname)s - %(message)s", #info incorporada
handlers=[
# salida por consola
logging.StreamHandler(),
# salida por archivo
logging.FileHandler(
filename=ruta_log,
mode="a",
encoding="utf-8",
delay=True,
),
],
)
try:
# el numero maximo a contar se asigna como argumento
n = int(sys.argv[1])
logging.info("Contando hasta %i", n)
except Exception:
# valor máximo por default en caso de error
logging.warning("Argumento de entrada faltante o incorrecto (debe ser un entero)")
n = 10
logging.warning("Contando hasta %i (valor default)", n)
finally:
# el contador se incrementa cada 1 segundo
i = 0
while i <= n:
logging.info("i: %4i",i)
sleep(1)
i += 1
# imagen de referencia
FROM python:alpine
# directorio de trabajo (se crea automáticamente)
WORKDIR /code
# copia de rutinas al directorio de trabajo
COPY demo/ ./
# comando, opciones y argumentos fijos
ENTRYPOINT ["python", "contar.py"]
# opciones y argumentos sobreescribibles
CMD ["4"]
A continuación se muestran varias implementaciones alternativas de la gestión de volumenes:
Manejo manual
Listar e inspeccionar
La lista de volumenes existentes se consulta
con el comando volume list
:
Los parámetros del volumen de interés
se consultan con el comando volume inspect
:
La ruta al contenido del volumen
se indica dentro del campo Mountpoint
.
Su valor se puede consultar así:
Accediendo a esta ruta se podrá acceder a los datos para realizar copias de seguridad, restablecer los datos, realizar una migración de plataforma, etc.
Gestión gráfica
Las aplicaciones de escritorio de Docker y de Podman permiten visualizar y administrar los volumenes existentes de manera gráfica.
Creación
Los volumenes se pueden crear deliberadamente
con el comando create
:
services:
volumen_nombre:
build: .
volumes:
- NOMBRE_VOLUMEN:/root/logs
volumes:
NOMBRE_VOLUMEN:
external: true
Borrado
A los volumenes
y a su contenido
se los borra
uno a uno
con el comando remove
:
Borrar no usados
Los volumenes no utilizados por ningún contenedor
se pueden borrar en masa automátícamente
con el comando prune
("podar"):
Esta opción debe usarse con mucho cuidado, dado que puede haber volumenes con datos de producción que estén huérfanos al momento de ejecutar este comando.