Docker + Mutagen

Despues de varias aventuras y - sobre todo - desventuras con brew, he tomado la decisión de minimizar - o intentarlo al menos - que las dependencias de mis múltiples entornos de desarrollo estén enganchadas o dependan - valga la redundancia - directamente del gestor de paquetes del sistema, por lo que pueda pasar.

Una decisión que me ha llevado a exprimir Docker un poco más de lo habitual. Pasar los proyectos de desarrollo activos - y los no muertos del todo, con cierta posibilidad de reactivación - a contenedores está siendo divertido y complicado a partes iguales.

Además de descubrir algunos trucos en relación al funcionamiento tanto de Docker como de Docker Compose, he visto que el rendimiento del mismo en MacOS - sobre todo en temas relacionados con IO - es muy mejorable.

A la hora de crear un contenedor para desarrollo, el concepto de volumen es primordial puesto que se trata del mecanismo que usa Docker para compartir archivos entre el propio contenedor y la máquina madre. Por ejemplo si estamos desarrollando un proyecto, querremos que el código fuente de ese proyecto permanezca en nuestra máquina madre o host (MacOS en mi caso) que es donde lanzaremos nuestro editor, pero a la vez ese código también tiene que estar disponbile dentro del contenedo que lo va a servir.

Esto que en teoría es tan simple (-v ~/code/proyecto/src:/var/www/html) lleva por debajo un montón de operaciones y lógica que hacen que, cuando la cantidad de archivos a compartir entre el host y el contenedor sea medianamente grande (>15k-20k), el rendimiento del servidor dockerizado se vea bastante afectado. Y a día de hoy, entre node_modules, vendors y demás librerías de terceros que usamos para cualquier cosa (tanto nosotros directamente como cualquier framework de cualquier lenguaje moderno) es más fácil de lo que parece llegar a esos números y empezar a notar ralentizaciones. Hay un montón de issues al respecto, pero creo que ésta refleja muy bien el punto en el que está el tema.

Por lo que he visto esto no pasa en Linux, sin embargo en MacOS todas las estrategias de sincronizado que he probado no han acabado de cuajar, sí es cierto que algunas mejoran un pelín el rendimiento pero ninguna me había dejado con la boca abierta (osxfs, rsync, unison...).

Hasta que llegué a este twitt de Jeff Geerling donde decía haber probado un binario de Docker parcheado con Mutagen que hacía que los tiempos (en su caso de un composer install) prácticamente se igualaban a los del stack nativo (en su caso LAMP instalado y configurado directamente en MacOS). Mezcla de sentimientos al leerlo, si el bueno de Jeff lo ha probado no creo que sea fake... pero por otro lado demasiado bonito para ser verdad.

Así que me permití la licencia de probarlo en uno de mis proyectos. Para probarlo he tenido que:

  • Descargar e instalar la versión Edge de Docker que trae Mutagen builtin (ojo porque se destruirán todos los contenedores activos).
  • Abrir Docker Desktop > Preferences > Resources > File Sharing y agregar ahí el directorio del volumen a montar que queremos que se comparta con Mutagen.
  • Aplicar, Reiniciar Docker y esperar a que se cachee ese directorio. Al acabar pasará a un status "Ready".
  • Nos aseguramos de que estamos montando el mismo directorio en nuestro docker-compose o en nuestra llamada a Docker.
  • Levantamos nuestro(s) contenedor(es) y volvemos a Docker Desktop, inspeccionamos el contenedor que debería tener ese volumen montado y comprobamos que el punto de montaje apunta a /var/lib/mutagen/uuid en vez de apuntar a la ruta que hemos especificado al arrancar el contenedor (docker-compose.yml ó script de llamada a Docker).
  • Una vez hecho esto podemos hacer las comprobaciones necesarias para darnos cuenta de que nuestro volumen ya responde a velocidad casi nativa.

En mi caso particular los números - redondeados en una media de 10 peticiones - hablan de unas velocidades de carga del /dashboard del proyecto tales que los siguientes:

  • Nativo MacOSX ~=   110ms
  • Docker normal ~=  1000ms
  • Docker Mutagen ~=  130ms

Nativo MacOS

Docker Stable

Docker Edge + Mutagen

TL;DR

Docker + Mutagen all the things!. Espero que pronto lo agreguen por defecto a la build oficial, aunque consume un poco más de CPU al hacer el build y de disco (porque tiene que cachear todos eso directorios compartidos) merece mucho la pena y ahorra bastante tiempo en fase de desarrollo.

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.