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

前端 未结 5 1067
再見小時候
再見小時候 2021-02-02 10:22

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 machin

相关标签:
5条回答
  • 2021-02-02 10:33

    If you are using bridge networking for your containers, and you don't want to install node-inspector inside the same container as your node process, I've found this to be a convenient solution:

    • In the main node.js container, map port 5858 to the host
    • Run the main node process with debug enabled
    • Use a separate container for running node-inspector
    • Use host networking for the node-inspector container

    This say, the node-inspector container will connect to localhost:5858 which will then be port mapped through to the main node container.

    If you're running this on a public VM, I'd then recommend:

    • Make sure port 5900 is not exposed publicly (e.g. by the firewall)
    • Make sure the node inspector port (e.g. 8080) us exposed publicly, so you can connect to it

    I wrote a few more details about it here: https://keylocation.sg/our-tech/debugging-nodejs-in-docker-using-node-inspector

    0 讨论(0)
  • 2021-02-02 10:36

    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

    0 讨论(0)
  • 2021-02-02 10:38

    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".} ]..                                                                   
    #
    
    0 讨论(0)
  • 2021-02-02 10:45

    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 .
    0 讨论(0)
  • 2021-02-02 10:51

    As far as I can see, you need to provide the parameter --debug-brk= to node upon startup - this will enable debugging. After that, access the specified port on your docker container. You probably have to expose it or tunnel (using ssh).

    After that, point the Webstorm remote debugger at the specified port, and you should be set.

    0 讨论(0)
提交回复
热议问题