Además de los volúmenes, existe otra alternativa para disponer de datos persistentes en un contenedor. Aunque su origen se remonta a los primeros días de Docker, sus posibilidades resultan un tanto limitadas. Sin embargo, saber de su existencia puede resultar útil en determinados casos que comentaremos más adelante. En esta guía aprenderás cómo utilizar bind mounts en Docker sobre Ubuntu 20.04.
Las características más distintivas de los bind mounts son las siguientes:
- Un directorio cualquiera del sistema host puede montarse en el contenedor.
- Los procesos del contenedor tienen acceso a tal directorio, por lo que pueden llegar a crear, modificar, o borrar su contenido. Por supuesto, existe la posibilidad de montar el directorio como solo lectura para resolver este inconveniente.
- Permiten compartir archivos de configuración desde el host hacia el contenedor. De hecho, Docker realiza la resolución de nombres montando el archivo /etc/resolv.conf del sistema anfitrión en cada contenedor.
Por estas razones, no resultan la mejor opción bajo ciertos escenarios (en los cuales los volúmenes son la decisión más acertada):
- Cuando necesitemos compartir datos entre varios contenedores en ejecución, o si los archivos se encuentran en un host remoto.
- Si no tenemos la seguridad de que el host tendrá una estructura determinada en el sistema de archivos.
- Para migrar datos de un host a otro (no entre contenedores).
- En caso de que se desee usar la CLI de Docker para manejar directamente el recurso de almacenamiento.
La documentación oficial de Docker contiene una comparación más detallada sobre volúmenes y bind mounts. Además, detalla una lista de casos de uso para cada uno.
Requisitos previos
- Completar los pasos detallados en Instalar Docker y crear un contenedor en Ubuntu 20.04.
- Crear una regla en el cortafuegos de Donweb que abra el puerto 8080/TCP. Si necesitas instrucciones para completar este punto, puedes referirte al artículo Firewall en la sección de ayuda.
Paso 1: Creación del directorio para el bind mount
En esta instancia, simplemente vamos a crear un nuevo directorio para alojar un simple index.html. Para propósitos ilustrativos, no hará falta que tenga la estructura formal de un documento HTML.
mkdir ~/website
cd ~/website
echo "Soy un archivo en un bind mount" > index.html
Para agregar más contenido después, no hay necesidad de recrear el contenedor que usará el bind mount.
Paso 2: Ejecución del contenedor
Para comenzar, recordemos el comando para crear un contenedor basado en la imagen oficial de Nginx:
sudo docker container run --name=nginx --publish 8080:80 --detach --restart=always nginx
Antes de ejecutarlo, agreguemos la opción -v seguida de:
- la ruta al directorio que creamos en el paso anterior,
- dos puntos, y
- la ubicación donde deseamos montarlo en el contenedor
sudo docker container run --name=nginx -v ~/website:/usr/share/nginx/html --publish 8080:80 --detach --restart=always nginx
Ahora sí podemos presionar Enter y esperar el resultado. Una vez que el contenedor esté ejecutándose, inspeccionemos su configuración con especial atención a la sección Mounts:
sudo docker container inspect nginx
La información más relevante que muestra la imagen de arriba es:
- La solución de almacenamiento (Type)
- El origen o Source (/home/gabriel/website dentro del sistema anfitrión)
- El destino o Destination (/usr/share/nginx/html en el contenedor)
- El modo (RW: read/write, o lectura/escritura)
Ahora nos damos cuenta de que no especificamos que el bind mount fuera de solo lectura. ¡No importa! Podemos detener el contenedor, eliminarlo, volver a crearlo con la opción :ro
acompañando a -v
:
sudo docker container stop nginx
sudo docker container rm nginx
sudo docker container run --name=nginx -v ~/website:/usr/share/nginx/html:ro --publish 8080:80 --detach --restart=always nginx
Al finalizar, volvamos a inspeccionar la nueva sección Mounts:
De esta manera, los procesos del contenedor no podrán modificar el contenido del directorio origen.
Paso 3: Manipulación del contenido del bind mount
Con el contenedor en ejecución, accedamos a la raíz del sitio desde un navegador:
Y ahora modifiquemos su contenido para luego refrescar la página:
echo "<br>Hoy es $(date +%d/%m/%Y)" >> ~/website/index.html
Como podemos ver, el contenido se actualizó como esperábamos. Este ejemplo, si bien simple, nos permite ver una ventaja de los bind mounts. Podemos emplearlos ya que son fáciles de utilizar para desarrollar una aplicación, guardar cambios, y ver su efecto en el contenedor de forma rápida.
Conclusión
En esta guía aprendiste cómo utilizar bind mounts para solucionar la necesidad de persistencia. Al repasar la lista de características que compartimos en la introducción podrás identificar si representa la mejor alternativa. En caso de que no lo sea, siempre puedes recurrir a los volúmenes y contar con todas las herramientas de la CLI de Docker.