发布于 5年前

如何在Docker容器中调试Node.js应用程序

大多数情况下,您可以在本地计算机上运行应用程序,并仅使用容器来沙箱化数据库和消息队列,但是只有当应用程序本身也是容器化时,一些错误才会显示出来。在这些情况下,了解如何将调试器附加到服务非常有用。

此文中使用的所有代码段和设置都可以在其GitHub中找到。

如何使用 Node inspector

如果你主要使用print()进行调试,那么在短时间内找到正确的值是非常困难的。

如果每次调试添加console.log后都需要重建容器镜像,情况会变得更糟。只构建一次镜像并在其中来回操作,在运行时检查变量,可能要容易得多。为了更好地理解我们将要做的事情,我强烈建议您首先熟悉node inspect命令。

debug模式下运行你的 node 程序,只需要在node后添加inspect,比如:

$ node inspect index.js
< Debugger listening on ws://127.0.0.1:9229/5adb6217-0757-4761-95a2-6af0955d7d25
< For help, see: https://nodejs.org/en/docs/inspector
< Debugger attached.
Break on start in index.js:1
> 1 (function (exports, require, module, __filename, __dirname) { const http = require('http')
  2 const PORT = process.env.PORT || 3000
  3 
debug> 

当你在调试模式下运行代码时,它始终在第一行处停止,等待与其交互。对于那些习惯用gdb调试代码的人来说,这个界面可能很引人注目。但是,如果您习惯使用GUI调试器,则可能需要打开chrome并chrome://inspect

你应该能看到类似这样的页面:

在远程目标下,点击inspect,您将看到Chrome开发者工具调试器。

现在您可以根据需要使用调试器。现在,是时候将我们的应用程序放在容器中了。

调试容器中的 Node.js

首先,我们需要创建一个 Dockerfile

FROM node

COPY package.json package.json  
RUN npm install

COPY . .  

EXPOSE 3000
CMD ["node", "."]

和一个docker-compose.yaml

version: '3.6'

services:
  app: 
    build: .
    ports:
      - "3000:3000" 

现在,如果您运行docker-compose up,您将能够开始使用您的服务http://localhost:3000

接下来,让我们创建一个debug-compose.yaml

version: '3.6'

services:
  app: 
    build: .
    ports:
      - "3000:3000" 
      - "9229:9229"
    command:
      - node
      - "--inspect-brk=0.0.0.0"
      - "." 

如您所见,我们打开了端口9229,这是Node.js应用程序的调试端口。我们还覆盖了我们在Dockerfile中指定的命令。--inspect-brk=0.0.0.0 做了两件不同的事情:

  1. --inspect 告诉 Node 我们想要在调试模式下运行我们的应用程序。
  2. 通过添加-brk确保应用程序在第一行停止运行,因此我们有足够的时间来打开检查器。
  3. 添加=0.0.0.0保障任何IP的连接都可以打开调试器。

默认情况下,调试器绑定到127.0.0.1,因为我们通常不希望任何人都可以将调试器附加到我们的应用程序。容器是与主机不同的IP,因此我们无法访问它。只要我们能在本地这样做就可以了。但是,我们不希望在使用中的服务器上运行它。

因此,请确保它与docker-compose.yaml文件不同。

另请注意,端口转发规则包含在"-s中。如果省略引号,则规则可能不起作用。 尽管如此,您应该能够在开发工具中检查您的应用程序。

使用 Visual StudioCode 进行调试

使用 inspector 检查单个文件问题非常好用,但是在检索项目中的所有文件时可能会遇到问题。在这些情况下,最好连接IDE提供的调试器。让我们看看它是如何使用Visual Studio Code完成的。

首先,找到调试选项卡

然后单击齿轮图标

从弹出列表中选择docker(确保已安装Docker扩展)

它应该在项目.vscode文件夹中生成一个launch.json文件, 如所示:

这几乎没问题,但在我们的例子中,我们的应用程序的根目录是容器文件系统的根目录,所以我们还需要更新它。完成后,项目应如下所示:

{
  "name": "Docker: Attach to Node",
  "type": "node",
  "request": "attach",
  "port": 9229,
  "address": "localhost",
  "localRoot": "${workspaceFolder}",
  "remoteRoot": "/",
  "protocol": "inspector"
}

现在,如果你在键盘上点击F5,系统会提示你在VSCode中习惯使用的调试器。再次点击F5,让服务器开始监听。如果你在某个地方设置断点并调用服务器,http://localhost:3000你应该看到

为什么不是 ndb

虽然 ndb 很适合调试,但是你无法将它附加到当前正在运行的进程,这在我们的案例中几乎破坏了目的。

您也可以在容器内部启动调试程序并将调试器连接到外部,但是您还需要修改您Dockerfile,并且您实际上没有获得任何内容,因为您需要附加其他调试器。

©2020 edoou.com   京ICP备16001874号-3