使用 Docker 进行 NodeJS 远程调试
NodeJS Remote Debugging with Docker
两天过去了,我还是想不通这个本该很简单的事情!
我想:
- 创建一个nodejs docker swarm服务和运行 nodejs代码在
调试模式
- 向主机公开调试器端口
- 能够从主机连接到调试器
重现问题的最简单步骤:
root@host docker service create --name dbg-nodejs --publish 4444:4444 node sleep 10d
root@host containerID=$(docker container ls --filter name=dbg-nodejs | awk 'FNR == 2 {print }') ### find the containerId
root@host docker exec -d $containerID /bin/bash -c "(echo \"console.log('\n\n\nHello from NodeJS\n\n\n');\" > /usr/test-dbg.js) && node --inspect-brk=4444 /usr/test-dbg.js"
root@host docker exec $containerID /bin/bash -c "curl localhost:4444 -v" ### you see the output here! Great the debugging port is working within the container
root@host curl localhost:4444 -v ### aaahhhhh <<--- CANNOT CONNECT TO the published 4444 port!!!!!!
发布端口工作正常。如果我 运行 一个 netcat 在容器中监听 4444,它就可以正常工作!节点调试器以某种方式表现不同。但它不应该!这只是TCP! :/
更多信息:
因此,如果我不使用 node --inspect-brk=4444 /usr/test-dbg.js
而使用 netcat -l -p 4444
,则一切正常。即,使用默认入口网络,我可以从主机连接到容器。不知何故,行为是不同的!他们都是TCP。
绝对奇怪!但是端口转发解决了这个问题。一切都一样,除了:
- 我使用另一个端口来连接 nodejs 调试器,而不是 4444,例如端口 #5555
- 我使用
socat
使用此命令将 4444 转发到 5555:socat -v tcp-listen:4444,reuseaddr,fork tcp:localhost:5555
当然,你需要在你的docker容器上安装socat。但仅此而已!! Docker 对待 NodeJS 调试器 TCP 的方式与 socat TCP 不同!也许,NodeJS 调试器不监听所有网络接口上的端口,这使得它无法获取连接。
一个完整的例子:
root@host docker service create --name dbg-nodejs --publish 4444:4444 node sleep 10d
root@host containerID=$(docker container ls --filter name=dbg-nodejs | awk 'FNR == 2 {print }') ### find the containerId
root@host docker exec -d $containerID /bin/bash -c "(echo \"console.log('\n\n\nHello from NodeJS\n\n\n');\" > /usr/test-dbg.js) && node --inspect-brk=5555 /usr/test-dbg.js"
root@host docker exec $containerID /bin/bash -c "apt-get update && apt-get -y install socat"
root@host docker exec -d $containerID /bin/bash -c "socat -v tcp-listen:4444,reuseaddr,fork tcp:localhost:5555"
root@host docker exec $containerID /bin/bash -c "curl localhost:4444 -v" ### you see the output here! Great the debugging port is working within the container
root@host docker exec $containerID /bin/bash -c "curl localhost:5555 -v" ### you will see the same as we forwarded 5555 to 4444
root@host curl localhost:4444 -v ### <<--- IT WORKS!! 4444@host --> 4444@container --> 5555@container (nodejs debugger)
注意:当您看到 "WebSockets request was expected" 时,这意味着它实际上已连接并从调试器收到响应。
关于调试工具,我还没有找到使用webstorm的方法。但是 chrome 开发工具调试器工具和节点检查工作正常。对于 chrome 开发工具,当你 运行 带有 node --inspect-brk 标志时,只需从终端复制并粘贴输出。确保根据端口转发调整端口。 chrome 开发工具地址如下所示:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:38213/03b57c12-d8ca-4100-b852-1aacce107880
有关调试工具的更多详细信息:
https://nodejs.org/en/docs/inspector/
两天过去了,我还是想不通这个本该很简单的事情!
我想:
- 创建一个nodejs docker swarm服务和运行 nodejs代码在 调试模式
- 向主机公开调试器端口
- 能够从主机连接到调试器
重现问题的最简单步骤:
root@host docker service create --name dbg-nodejs --publish 4444:4444 node sleep 10d
root@host containerID=$(docker container ls --filter name=dbg-nodejs | awk 'FNR == 2 {print }') ### find the containerId
root@host docker exec -d $containerID /bin/bash -c "(echo \"console.log('\n\n\nHello from NodeJS\n\n\n');\" > /usr/test-dbg.js) && node --inspect-brk=4444 /usr/test-dbg.js"
root@host docker exec $containerID /bin/bash -c "curl localhost:4444 -v" ### you see the output here! Great the debugging port is working within the container
root@host curl localhost:4444 -v ### aaahhhhh <<--- CANNOT CONNECT TO the published 4444 port!!!!!!
发布端口工作正常。如果我 运行 一个 netcat 在容器中监听 4444,它就可以正常工作!节点调试器以某种方式表现不同。但它不应该!这只是TCP! :/
更多信息:
因此,如果我不使用 node --inspect-brk=4444 /usr/test-dbg.js
而使用 netcat -l -p 4444
,则一切正常。即,使用默认入口网络,我可以从主机连接到容器。不知何故,行为是不同的!他们都是TCP。
绝对奇怪!但是端口转发解决了这个问题。一切都一样,除了:
- 我使用另一个端口来连接 nodejs 调试器,而不是 4444,例如端口 #5555
- 我使用
socat
使用此命令将 4444 转发到 5555:socat -v tcp-listen:4444,reuseaddr,fork tcp:localhost:5555
当然,你需要在你的docker容器上安装socat。但仅此而已!! Docker 对待 NodeJS 调试器 TCP 的方式与 socat TCP 不同!也许,NodeJS 调试器不监听所有网络接口上的端口,这使得它无法获取连接。
一个完整的例子:
root@host docker service create --name dbg-nodejs --publish 4444:4444 node sleep 10d
root@host containerID=$(docker container ls --filter name=dbg-nodejs | awk 'FNR == 2 {print }') ### find the containerId
root@host docker exec -d $containerID /bin/bash -c "(echo \"console.log('\n\n\nHello from NodeJS\n\n\n');\" > /usr/test-dbg.js) && node --inspect-brk=5555 /usr/test-dbg.js"
root@host docker exec $containerID /bin/bash -c "apt-get update && apt-get -y install socat"
root@host docker exec -d $containerID /bin/bash -c "socat -v tcp-listen:4444,reuseaddr,fork tcp:localhost:5555"
root@host docker exec $containerID /bin/bash -c "curl localhost:4444 -v" ### you see the output here! Great the debugging port is working within the container
root@host docker exec $containerID /bin/bash -c "curl localhost:5555 -v" ### you will see the same as we forwarded 5555 to 4444
root@host curl localhost:4444 -v ### <<--- IT WORKS!! 4444@host --> 4444@container --> 5555@container (nodejs debugger)
注意:当您看到 "WebSockets request was expected" 时,这意味着它实际上已连接并从调试器收到响应。
关于调试工具,我还没有找到使用webstorm的方法。但是 chrome 开发工具调试器工具和节点检查工作正常。对于 chrome 开发工具,当你 运行 带有 node --inspect-brk 标志时,只需从终端复制并粘贴输出。确保根据端口转发调整端口。 chrome 开发工具地址如下所示:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:38213/03b57c12-d8ca-4100-b852-1aacce107880
有关调试工具的更多详细信息: https://nodejs.org/en/docs/inspector/