如何通过Google Cloud调试运行在Docker容器中的Nodejs应用程序

26
我发现Google提供了一些关于如何在自定义运行环境上运行Nodejs的指南。一切看起来都很好,我成功地在本地机器上运行了我的Nodejs应用程序,运行命令为gcloud preview app run .
从我所看到的情况来看,它可能创建了一个Docker容器并在其中运行Nodejs程序。我说"可能",因为这是我第一次使用Docker,但我是一名有2年以上经验的Nodejs开发人员。

所以我的问题是如何在Docker容器内运行时调试(使用断点停止)我的Nodejs程序?使用Chrome开发者工具或如何设置Webstorm调试配置使其在断点处停止。是否可以配置Docker以控制它如何启动node,甚至通过gcloud在Webstorm中启动Docker以确保调试正常工作?任何帮助或澄清都将不胜感激。

请不要提供有关如何在Docker容器外调试Nodejs应用程序的答案——我非常熟悉如何做到这一点。

5个回答

11

很抱歉,我只知道使用node-inspector的解决方案,希望它能对你有所帮助:


2
确认我能够在Chrome中使用Docker for Mac启动调试会话,使用docker-compose端口部分的5858:5858。使用默认的Docker网络模式。不需要--net=host、SSH转发或任何其他技巧。这就是Docker的本意(隔离)。另外,--web-host 0.0.0.0,这个并不是到处都提到的,是我配置中缺失的部分。没有它,node-debug会启动,但是无法从外部连接(连接被拒绝)。有了它,“一切正常”。 - amateur barista
Node-inspector启动和文件加载到浏览器源代码之间存在相当长的滞后时间。有什么想法为什么会这样? - Jeremy

9
从 Docker 0.11 开始,有一种更简单的方法。
只需在开发机上运行 Docker --net="host" 命令。这样 Docker 将直接绑定到本地主机,不会创建桥接网络适配器,因此 Docker 容器像您机器上的任何其他进程一样运行,并在本地接口上打开所需端口。
这样,您就可以像 Node 不在 Docker 内部运行一样连接到调试端口。
更多文档请参见:https://docs.docker.com/reference/run/ 在 Docker 0.11 之前,除了使用 node-inspector 进行调试外,还有其他两种调试方式:
1. 在 Docker 容器内运行 sshd 并设置 ssh 隧道,就像在远程机器上进行调试一样。
2. "搞乱" ip-tables 来 "撤销" Docker 映射的本地端口。有关详细信息,请参考Exposing a port on a live Docker container

7

默认情况下,节点调试器仅监听同一主机(127.0.0.1)的连接。但是在Docker中,您需要接受来自任何主机(0.0.0.0)的连接:

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

同时你需要暴露调试端口(9229)。然后应用程序应该会自动被检测并列在Chrome的chrome://inspect/#devices中作为远程目标(已在Chrome 67中测试)。

示例

以下是一个最小化的示例。它在Docker中运行一个简单的JavaScript应用程序,并展示如何将Chrome调试器连接到它:

$ 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

运行方式:

$ 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
...

打开 Chrome 浏览器并进入 chrome://inspect/#devices 页面,应用启动后,它会自动检测并列出应用程序。

故障排除

如果要调试 Docker 网络问题,可以使用docker inspect命令:

$ 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"
                }
            ]
        },
   ...

如果想查看Docker和Chrome之间发送的请求,可以使用ngrep工具:

$ 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".} ]..                                                                   
#

1
感谢@philipp-claßen�供的信�。0.0.0.0部分�常关键,�分感激。� - mraxus

0
据我所知,您需要在启动时向节点提供参数--debug-brk=,以启用调试。之后,访问您的docker容器上指定的端口。您可能需要将其暴露或通过ssh进行隧道传输。
之后,将Webstorm远程调试器指向指定的端口,然后您就可以开始了。

0

如果您正在为容器使用桥接网络,并且不想在与节点进程相同的容器中安装node-inspector,我发现以下是一个方便的解决方案:

  • 在主要的node.js容器中,将端口5858映射到主机
  • 启用调试模式运行主要的node进程
  • 使用单独的容器来运行node-inspector
  • 对于node-inspector容器,请使用主机网络

这样,node-inspector容器将连接到localhost:5858,然后通过端口映射连接到主要的node容器。

如果您在公共VM上运行此操作,则建议:

  • 确保端口5900未公开(例如通过防火墙)
  • 确保node inspector端口(例如8080)公开,以便您可以连接到它

我在这里写了更多详细信息:https://keylocation.sg/our-tech/debugging-nodejs-in-docker-using-node-inspector


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接