Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to debug Nodejs app running inside Docker container via Google Cloud

I have found Google provides some guidelines on how to run Nodejs on a custom runtime environment. Everything seems fine and I am managing to start my Nodejs app on local machine running gcloud preview app run ..
As I can see, it probably creates a Docker container and runs Nodejs program in there. I am saying "probably", because it is my first experience with Docker, however I am 2+ years experienced Nodejs developer.

So my question is how to debug (with breakpoint stops) my Nodejs program when it is running inside Docker container? Using Chrome Developer Tools or how can I set up Webstorm debug configuration to make it stop on breakpoints. Is it possible to configure Docker on how it starts node or even start Docker via gcloud inside Webstorm to assure debugging is working? Any help or clarifications are appreciated.

Please don't provide answers on how to debug Nodejs app outside of Docker container – I know how to do that very well.

like image 575
Nik Sumeiko Avatar asked Feb 14 '15 18:02

Nik Sumeiko


3 Answers

I'm sorry, but I only know a solution with node-inspector, I hope it can help you:

  • You can install node-inspector package inside your container: https://github.com/node-inspector/node-inspector
  • Map the port 8080 of your container on your host (run you container with parameter -p 8080:8080)
  • Run this inside your container (with docker exec, or docker-enter)

    node-debug --web-host 0.0.0.0 yourScript.js

  • Go to http://localhost:8080/debug?port=5858

like image 99
user1853777 Avatar answered Oct 24 '22 03:10

user1853777


There is an easier way, at least from Docker 0.11 or something.

Run, on your development machine only, Docker with --net="host". This makes Docker bind to the localhost directly, and not creating a bridging network adapter, so the Docker machine runs like any other process on your machine and opens the ports it needs on the local interface.

This way, you can connect to your debug port as if Node was not running inside Docker.

More documentation here : https://docs.docker.com/reference/run/

Before Docker 0.11 you have other two ways of debugging, apart from using node-inspector :

  • Run sshd inside your Docker machine and setup an ssh tunnel, as if you were to debug on a remote machine.
  • "Mess up" with ip-tables to "revert" the Docker mapping of local ports. There is something about it here Exposing a port on a live Docker container .
like image 40
Simone Gianni Avatar answered Oct 24 '22 04:10

Simone Gianni


By default, the node debugger will listen only for connections for the same host (127.0.0.1). But in Docker, you need to accept connections from any host (0.0.0.0):

# inside Docker
node --inspect=0.0.0.0:9229 myapp.js

Also you have to expose the debug port (9229). Then the application should be automatically detected and listed as a Remote Target in chrome://inspect/#devices in Chrome (tested in Chrome 67).

Example

Here is a minimal example. It runs a simple JavaScript application in Docker and shows how to attach the Chrome debugger to it:

$ cat example.js
setInterval(() => console.log('Hallo world'), 1000);

$ cat Dockerfile
FROM node
COPY example.js /
CMD node --inspect=0.0.0.0:9229 /example.js

Run with:

$ docker build . -t myapp && docker run -p 9229:9229 --rm -it myapp
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM node
 ---> aa3e171e4e95
Step 2/3 : COPY example.js /
 ---> Using cache
 ---> 3ef6c0311da2
Step 3/3 : CMD node --inspect=0.0.0.0:9229 /example.js
 ---> Using cache
 ---> e760739c2802
Successfully built e760739c2802
Successfully tagged debug-docker:latest
Debugger listening on ws://0.0.0.0:9229/4177f6cc-85e4-44c6-9ba3-5d8e28e1b124
For help see https://nodejs.org/en/docs/inspector
Hallo world
Hallo world
Hallo world
...

Open Chrome and go to chrome://inspect/#devices. It should soon after the start of the application, detect it and list it.

Troubleshooting

For debugging Docker network issues, docker inspect is useful:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
ae83d50e24c8        debug-docker        "/bin/sh -c 'node --…"   2 minutes ago       Up 2 minutes        0.0.0.0:9229->9229/tcp   blissful_sammet
$ docker inspect ae83d50e24c8
...
    "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "682d3ac98b63d4077c5d66a516666b6615327cbea0de8b0a7a2d8caf5995b0ae",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {
            "9229/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "9229"
                }
            ]
        },
   ...

If want to see the requests sent between Docker and Chrome, ngrep can help:

$ sudo ngrep -d any port 9229
interface: any
filter: (ip or ip6) and ( port 9229 )
############################
T ::1:38366 -> ::1:9229 [AP]
  GET /json/version HTTP/1.1..Host: [::1]:9229....                            
#####
T ::1:38368 -> ::1:9229 [AP]
  GET /json HTTP/1.1..Host: [::1]:9229....                                    
##############
T 172.17.0.1:56782 -> 172.17.0.2:9229 [AP]
  GET /json HTTP/1.1..Host: [::1]:9229....                                    
#
T 172.17.0.1:56782 -> 172.17.0.2:9229 [AP]
  GET /json HTTP/1.1..Host: [::1]:9229....                                    
###
T 172.17.0.1:56784 -> 172.17.0.2:9229 [AP]
  GET /json/version HTTP/1.1..Host: [::1]:9229....                            
#
T 172.17.0.1:56784 -> 172.17.0.2:9229 [AP]
  GET /json/version HTTP/1.1..Host: [::1]:9229....                            
###
T 172.17.0.2:9229 -> 172.17.0.1:56782 [AP]
  HTTP/1.0 200 OK..Content-Type: application/json; charset=UTF-8..Cache-Contro
  l: no-cache..Content-Length: 465....                                        
#
T 172.17.0.2:9229 -> 172.17.0.1:56782 [AP]
  HTTP/1.0 200 OK..Content-Type: application/json; charset=UTF-8..Cache-Contro
  l: no-cache..Content-Length: 465....                                        
###
T 172.17.0.2:9229 -> 172.17.0.1:56782 [AP]
  [ {.  "description": "node.js instance",.  "devtoolsFrontendUrl": "chrome-de
  vtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=[::
  1]:9229/f29686f9-e92d-45f4-b7a2-f198ebfc7a8e",.  "faviconUrl": "https://node
  js.org/static/favicon.ico",.  "id": "f29686f9-e92d-45f4-b7a2-f198ebfc7a8e",.
    "title": "/example.js",.  "type": "node",.  "url": "file:///example.js",. 
   "webSocketDebuggerUrl": "ws://[::1]:9229/f29686f9-e92d-45f4-b7a2-f198ebfc7a
  8e".} ]..                                                                   
#
like image 6
Philipp Claßen Avatar answered Oct 24 '22 03:10

Philipp Claßen