问题
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.
回答1:
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
回答2:
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 .
回答3:
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".} ]..
#
回答4:
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.
回答5:
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
来源:https://stackoverflow.com/questions/28518535/how-to-debug-nodejs-app-running-inside-docker-container-via-google-cloud