Ejecutar el debugger de node con chrome

Usar Docker para desarrollar una aplicación Node es cada vez más común. Sin embargo, eso complica un poco la ejecución del debugger que está configurado de forma predeterminada para funcionar en un ambiente completamente local.

Ahora voy a mostrar como podemos ejecutar el debugger de Node y seguir la ejecución de una aplicación que corre desde un contenedor Docker usando solamente las herramientas incluidas en el navegador Chrome.

Antes de iniciar

Primero hay que asegurarse de que tenemos una imagen de Node para iniciar contenedores basados en ella. Si aún no tienes una imagen de Node puedes cargar una con el comando: docker pull node.

Empecemos con una aplicación sencilla que solamente muestre un mensaje en la consola cuando el programa inicia y que después hace la suma de 1+1 guardando el resultado en una contante para finalmente mostrar el resultado de la suma en consola.

// index.js

console.log("El script ha iniciado")
debugger
const  a = 1 + 1
console.log(`El resultado final es: ${a}`)

Es un script sencillo pero suficiente para ilustrar el punto. Ahora vamos a arrancar el contenedor que ejecutará este script.

Primero debemos abrir una terminal y cambiarnos al directorio donde está guardado el script.

Si estás intentado seguir estos pasos desde una computadora con Linux o MacOS tal vez quieras modificar los permisos del script antes de continuar. Debería funcionar con algo como chmod 777 index.js

Ejecutar el debugger de node desde Docker

Ahora iniciamos el contenedor con el siguiente comando: docker run --rm -it --name test -v C:\Users\lalo\debugger:/usr/src/app -w /usr/src/app -p 9229:9229 node node --inspect-brk=0.0.0.0:9229 index.js

Veamos que hace cada modificador del comando:

  • docker run. Iniciamos un nuevo contenedor
  • --rm. El contenedor será eliminado al terminar la ejecución del proceso
  • -it. El proceso va a interactuar con nuestra terminal recibiendo y enviando texto
  • --name test. El contenedor tendrá un nombre para poder identificarlo entre los demás procesos que ejecute Docker. Si no usamos este modificador Docker le asignará un nombre aleatorio
  • -v C:\Users\lalo\debugger:/usr/src/app. Con esto montamos el folder local de nuestra computadora en el directorio /usr/src/app del contenedor que estamos creando. Tendrás que reemplazar C:\Users\lalo\debugger por la ruta que aplique en tu caso
  • -w /usr/src/app. Cambiamos el directorio de trabajo dentro del contedor a /usr/src/app (es donde la imagen de Node ejecuta los scripts de forma predeterminada). Es como si una vez iniciado el contenedor ejecutaramos cd /usr/src/app
  • -p 9229:9229. Dirigimos el tráfico del puerto 9229 de nuestra computadora al puerto 9229 dentro del contenedor que estamos creando. Lo necesitamos porque es el puerto que usará el debugger para establecer conexiones remotas
  • node node --inspect-brk=0.0.0.0:9229 index.js. El primer node es el nombre de la imagen que usaremos. Si tienes varias imagenes de Node puedes especificar la versión con algo como node:13.7.0 por ejemplo. El resto es el comando que queremos ejecutar dentro del contenedor. En este caso vamos a ejecutar node --inspect-brk=0.0.0.0:9229 index.js (detalles de esto más adelante )

Si todo sale bien deberías ver que Docker empieza a crear el contenedor y ejecuta el script de prueba en modo debugger.

Debugger listening on ws://0.0.0.0:9229/271b253c-2b67-4b69-802d-d0820ab8c49a
For help, see: https://nodejs.org/en/docs/inspector

El proceso se va a quedar congelado ahí hasta que iniciemos algún cliente de debugger y reanudemos la ejecución del script.

Conectar las herramientas de desarrollo de chrome al contenedor

Ahora podemos iniciar el navegador chrome y abrir la siguiente URL: chrome://inspect/

Hay que asegurarse de que tenemos dada de alta una dirección que apunte a algún proceso en modo debugger y esperar pacientemente a que chrome se conecte ya que no muestra algún indicador que nos haga saber que está trabajando en hacer la conexión.

node debugger docker chrome 2

Una vez que se ha establecido la conexión solamente tenemos que seguir el enlace que abrirá las DevTools de chrome con nuestro script cargado y listo para ser inspeccionado.

node debugger docker chrome 3

Hay que recordar que una vez que se abre la ventana de desarrollo de chrome tenemos que presionar el botón para reanudar la ejecución del script ya que el interprete se detiene antes de comenzar a ejecutar nuestro código.

node debugger docker chrome 4

Al reanudar la ejecución podemos ver que el primer mensaje ha sido desplegado con éxito en la consola y que el interprete se ha detenido en el punto de paro que hemos establecido.

Podemos usar las herramientas de chrome como sea necesario y reanudar la ejecución de nuestro programa cuando hayamos terminado.

¿Cómo se usa el debugger de Node con Docker?

Ahora voy a explicar con más detalle como funciona la configuración del debbuger.

Para indicarle a node que queremos ejecutar nuestro script con capacidad de debugger agregamos la opcion --inspect-brk. Con esto activamos el debugger y hacemos que la ejecución se detenga antes de empezar a interpretar nuestro programa hasta que reanudamos la ejecución manualmente desde el cliente de debugger.

Esto es necesario cuando ejecutamos programas que terminan el proceso inmediatamente después de interpretar todo nuestro código, de lo contrario el programa iniciaría y terminaría mucho antes de que chrome tuviera oportunidad de conectarse al debugger.

Si estamos ejecutando un programa de ejecución continua como por ejemplo una API hecha con Express, entonces tal vez no es necesario usar --inspect-brk sino la opción --inspect, que es prácticamente igual con la diferencia de que no va a detener el proceso al inicio sino hasta que encuentre el primer punto de paro en nuestro código. Esto depende mucho de como funcione tu programa y en que punto de la ejecución te interese hacer una pausa; recuerda que chrome necesita mucho tiempo para poder conectarse al proceso de debugger.

Tanto --inspect como --inspect-brk necesitan información adicional para funcionar desde un contenedor Docker. La configuración predeterminada no permite conectarse de forma remota, por eso hay que configurar una IP y un puerto para tener acceso remoto. En este caso lo conseguimos agregando los valores =0.0.0.0:9229 para permitir el acceso desde cualquier interface de red por el puerto 9229.

⚠ Será necesario cerrar la ventana de DevTools de chrome y volver a abrir el enlace de la página chrome://inspect cada vez que realices un cambio en el código. Recuerda que chrome necesita tiempo para volver a conectarse al debugger y cargar las herramientas de desarrollo con la nueva versión de tu código.

Alerta de seguridad

Aunque puede ser una herramienta muy útil, el modo de debugger no es una opción segura para ser usada en ambientes de producción. La recomendación oficial es que esta característica se mantenga desactivada mientras nuestra aplicación está siendo usada por usuarios reales en un ambiente de instalación real.

Conclusión

Esta es una forma rápida de configurar tu ambiente de desarrollo para ejecutar el debugger para una aplicación hecha con Node y ejecutada desde un contenedor Docker usando las herramientas de desarrollador del navegador chrome.

En otra ocasión mostraré como usar el debugger desde otros clientes como por ejemplo desde Visual Studio Code.

Hasta la próxima 👋.

About the author

Eduardo es un nerd apasionado por la tecnología. Se ha dedicado a investigar y poner en práctica distintos lenguajes de programación desde los 16 años de edad y actualmente trabaja como ingeniero de software para empresas de USA y Canadá. Siempre disfruta compartiendo los resultados de sus experimentos tecnológicos con todos los que conoce y aprender algo más en el proceso.

Read next: