调试在Docker容器中运行的Node.js应用程序的14个步骤

本文详述了如何调试运行在Docker容器内的Node.js应用程序,包括先决条件(Docker、Node.js、Visual Studio Code)、初始化Todo应用、创建Docker镜像、在VS Code中启用调试,并通过实例演示如何识别并修复代码错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇博客文章显示了如何调试运行在Docker容器中的简单Node.js应用程序。 本教程的布局方式允许您在构建自己的Node.js应用程序时将其用作参考,并且适合那些事先接触过JavaScript编程和Docker的读者。

先决条件

1. Docker 。 有关安装Docker的详细信息,请参阅“ 安装Docker”页面。

2. Node.js 10或更高版本。 要检查您的计算机上是否安装了Node.js,请启动终端窗口并键入以下命令:

node -v

如果已经安装了Node.js,您将看到类似以下内容:

v10.15.3

如果未安装Node.js,则可以从“ 下载”页面下载安装程序。

3. Microsoft Visual Studio 。 有关如何安装Visual Studio的详细信息,请参阅“ 安装Visual Studio”页面。

初始化您的Todo应用程序

在本教程的范围内,我们将创建一个准任务列表,允许用户添加和删除任务。 应用程序中将存在一个小错误,我们将使用Visual Studio Code调试代码并解决问题。 您将在本教程中获得的知识将帮助您调试自己的应用程序。 让我们开始吧。

1.启动一个新的终端窗口,移至您的项目目录,然后执行以下命令:

mkdir MyTodoApp &&cd MyTodoApp

2.通过以下方式初始化项目:

npm init -y

这将输出如下内容:

Wrote to /Users/ProspectOne/Documents/MyTodoApp/package.json:

{"name" : "MyTodoApp" ,
  "version" : "1.0.0" ,
  "description" : "" ,
  "main" : "index.js" ,
  "scripts" : {
    "test" : "echo \"Error: no test specified\" && exit 1"
  },
  "keywords" : [],
  "author" : "" ,
  "license" : "ISC"
}

创建准系统Todo应用程序

我们将使用Express来构建待办应用程序, Express是Node.js的快速,不受限制的极简主义Web框架。 Express旨在使开发网站变得更加容易,它是最受欢迎的Node.js Web框架之一。

1.通过输入以下命令来安装express和其他一些先决条件:

npm install express body-parser cookie-session ejs  --save
> ejs@3.0.1 postinstall /Users/ProspectOne/Documents/test /MyTodoApp/node_modules/ejs
> node ./postinstall.js

Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN MyTodoApp@1.0.0 No description
npm WARN MyTodoApp@1.0.0 No repository field.

+ ejs@3.0.1
+ body-parser@1.19.0
+ express@4.17.1
+ cookie-session@1.3.3
added 55 packages from 39 contributors and audited 166 packages in 6.533s
found 0 vulnerabilities

2.创建一个名为app.js的文件,其内容如下:

const express = require('express' )
const app = express()
const bodyParser = require( 'body-parser' )
const session = require( 'cookie-session' )
const urlencodedParser = bodyParser.urlencoded({ extended: false })
const port = 3000

app.use(session({ secret: process.env.SECRET }))
  .use( function (req, res, next) {
    next()
  })

  .get ( '/todo' , function (req, res) {
    res.render( 'todo.ejs' , { todolist: req.session.todolist })
  })

  .post ( '/todo/add/' , urlencodedParser, function (req, res) {
    if (req.body.newtodo != '' ) {
      req.session.todolist.push(req.body.newtodo)
    }
    res.redirect( '/todo' )
  })

  .get ( '/todo/delete/:id' , function (req, res) {
    if (req.params.id != '' ) {
      req.session.todolist.splice(req.params.id, 1)
    }
    res.redirect( '/todo' )
  })

  .use ( function (req, res, next) {
    res.redirect( '/todo' )
  })


  .listen(port, () => console.log(`MyTodo app is listening on port ${port} !`))

请注意,上面的代码片段是openclassroom.com网站上的代码的衍生产品,并且解释此代码的工作方式不在本教程的讨论范围之内。 如果细节不清楚,建议您在完成本教程后访问其站点,以进一步学习。

3.创建一个名为./views/todo.ejs的文件,并将以下内容粘贴到其中:

<!DOCTYPE html>

<html>
    <head>
        <title>My todolist</title>
        <style>
            a {text-decoration: none; color: black;}
        </style>
    </head>

    <body>
        <h1>My todolist</h1>

        <ul>
        <% todolist.forEach(function (todo, index) { %>
            <li><a href= "/todo/delete/<%= index %>" >✘</a> <%= todo %></li>
        <% }); %>
        </ul>

        <form action= "/todo/add/" method= "post" >
            <p>
                <label for = "newtodo" >What should I do ?</label>
                <input type = "text" name= "newtodo" id= "newtodo" autofocus />
                <input type = "submit" />
            </p>
        </form>
    </body>
</html>

4.此时,您的目录结构应类似于以下内容:

tree -L 2 -I node_modules
.
├── app.js
├── package-lock.json
├── package.json
└── views
    └── todo.ejs

1 directory, 4 files

5.现在,您可以通过输入以下内容来启动Web服务器:

SECRET=bestkeptsecret; node app.js

这会将以下消息打印到控制台:

MyTodo app is listening on port 3000!

创建一个Docker镜像

既然您已经编写了Todo应用程序,现在该为它添加创建Docker映像了。 每个Docker容器均基于Docker映像,该映像包含使用Docker部署和运行应用程序所需的所有信息。 要运行Docker容器,您可以:

  • 下载现有的Docker映像
  • 创建自己的图像

在本教程中,您将创建自己的图像。 请注意,Docker映像通常由多层组成,并且每一层基本上都是只读文件系统。 这种工作方式是,Docker为在Dockerfile中找到的每条指令创建一个层,并将其放置在先前层的顶部。 放置经常更改的应用程序代码靠近文件底部被认为是一种好习惯。

1.创建一个名为Dockerfile的文件,并将以下代码片段粘贴到其中:

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node" , "app.js" ]

让我们仔细看一下这个文件:

  • FROM :设置基本图像。 您稍后添加的所有内容都将基于该图像。 在此示例中,我们使用的是Node.js版本10。
  • WORKDIR :此命令设置将用于COPY,RUN和CMD命令的工作目录。
  • RUN :这行代码在Docker容器内运行npm install命令。
  • COPY :将文件从构建上下文复制到Docker映像中
  • EXPOSE :指定在容器内部运行的进程正在侦听3000端口。 当您将端口从主机转发到容器时,这将在本教程的后面部分很有用。
  • CMD仅在容器启动后,此行在Docker容器中运行node app.js

2.为避免将大文件发送到构建上下文并加快该过程,可以使用.dockerignore文件。 这不过是一个纯文本文件,其中包含应从构建中排除的文件和目录的名称。 您可以认为它类似于.gitignore文件。 创建一个名为.dockerignore的文件,其内容如下:

node_modules
npm-debug.log

3.现在,您可以通过输入docker build命令,然后依次输入以下内容来docker build Docker映像:

  • -t参数指定图像的名称
  • 上下文路径,该路径应指向您要从Dockerfile引用的文件集
docker build -t prospectone/my-todo-list .
Sending build context to Docker daemon  24.58kB
Step 1/7 : FROM node:10
 ---> c5d0d6dc0b5b
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 508b797a892e
Step 3/7 : COPY package*.json ./
 ---> 0b821f725c19
Step 4/7 : RUN npm install
 ---> Runningin d692a6278d2b

> ejs@3.0.1 postinstall /usr/src/app/node_modules/ejs
> node ./postinstall.js

Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)

npm WARN MyTodoApp@1.0.0 No description
npm WARN MyTodoApp@1.0.0 No repository field.

added 55 packages from 39 contributors and audited 166 packages in 2.564s
found 0 vulnerabilities

Removing intermediate container d692a6278d2b
 ---> 067de030e269
Step 5/7 : COPY . .
 ---> 3141ccb6e094
Step 6/7 : EXPOSE 3000
 ---> Running in eb824e38d8c6
Removing intermediate container eb824e38d8c6
 ---> b09d55adc1c4
Step 7/7 : CMD [ "node" , "app.js" ]
 ---> Running in 7e77e0cbfa75
Removing intermediate container 7e77e0cbfa75
 ---> c0a2db4c7a65
Successfully built c0a2db4c7a65
Successfully tagged prospectone/my-todo-list:latest

如上所述, docker build命令的工作方式是为Dockerfile中的每个命令添加一个新层。 然后,一旦命令成功执行,Docker就会删除中间容器。

4.现在,您已经构建了映像,让我们通过输入docker run命令并向其传递以下参数来docker run它:

  • -p ,将主机(3001)上的端口转发到容器(3000),并由:分隔:
  • -e创建一个称为SECRET的环境变量并将其值设置为bestkeptsecret
  • -d指定容器应在后台运行
  • 图像的名称( prospectone/my-awesome-app
docker run -p 3001:3000 -e SECRET=bestkeptsecret -d prospectone/my-todo-list
db16ed662e8a3e0a93f226ab873199713936bd687a4546d2fce93e678d131243

5.您可以验证您的Docker容器正在运行:

docker ps

输出应类似于:

CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                    NAMES
a6eb166191c7        prospectone/my-todo-list"docker-entrypoint.s…"   4 seconds ago       Up 3 seconds        0.0.0.0:3001->3000/tcp   happy_hawking

6.要检查日志,请输入docker logs命令,然后输入容器的id

docker logs a6eb166191c7
MyTodo app is listening on port 3000!

7.现在您的应用程序已启动并正在运行,将浏览器指向http:// localhost:3001,然后让我们添加一个新的待办事项。 如下所示,应用程序错误出现在todo.ejs文件的第15行:

在下一部分中,您将学习如何使用Visual Studio Code调试它。

8.但首先,使用以下方法停止容器:

dockerkill a6eb166191c7
a6eb166191c7

在Microsoft Visual Studio代码中启用调试

Visual Studio Code为运行在Docker容器中的Node.js应用程序提供调试支持。 请按照以下步骤启用此功能:

1.通过替换以下行来编辑您的Dockerfile:

CMD ["node" , "app.js" ]

与:

CMD ["npm" , "run" , "start-debug" ]

您的Dockerfile应该如下所示:

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm" , "run" , "start-debug" ]

2.打开package.json文件,并将以下行添加到scripts对象:

"start-debug" : "node --inspect=0.0.0.0 app.js"

此行代码启动Node.js进程,并在端口9229上侦听调试客户端。

这是package.json文件的外观:

{"name" : "MyTodoApp" ,
  "version" : "1.0.0" ,
  "description" : "" ,
  "main" : "index.js" ,
  "scripts" : {
    "test" : "echo \"Error: no test specified\" && exit 1" ,
    "start-debug" : "node --inspect=0.0.0.0 app.js"
  },
  "keywords" : [],
  "author" : "" ,
  "license" : "ISC" ,
  "dependencies" : {
    "body-parser" : "^1.19.0" ,
    "cookie-session" : "^1.3.3" ,
    "ejs" : "^3.0.1" ,
    "express" : "^4.17.1"
  }
}

3.每次更新Dockerfile时,都必须再次构建Docker映像:

docker build -t prospectone/my-todo-list .
Sending build context to Docker daemon  19.97kB
Step 1/7 : FROM node:10
 ---> c5d0d6dc0b5b
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 508b797a892e
Step 3/7 : COPY package*.json ./
 ---> c0eec534b176
Step 4/7 : RUN npm install
 ---> Runningin a155901cb957
npm WARN MyAwesomeApp@1.0.0 No description
npm WARN MyAwesomeApp@1.0.0 No repository field.

added 50 packages from 37 contributors and audited 126 packages in 11.504s
found 0 vulnerabilities

Removing intermediate container a155901cb957
 ---> 010473a35e41
Step 5/7 : COPY . .
 ---> 76dfa12d4db4
Step 6/7 : EXPOSE 3000
 ---> Running in b5a334c9a2ea
Removing intermediate container b5a334c9a2ea
 ---> b5a869ab5441
Step 7/7 : CMD [ "npm" , "run" , "start-debug" ]
 ---> Running in 1beb2ca9a391
Removing intermediate container 1beb2ca9a391
 ---> 157b7d4cb77b
Successfully built 157b7d4cb77b
Successfully tagged prospectone/my-todo-list:latest

请注意,步骤7已更新,这意味着Docker现在将执行npm run start-debug命令。

4.要启用Visual Studio Code调试,还必须转发端口9229 。 通过输入以下内容来启动您的Docker容器:

docker run -p 3001:3000 -p 9229:9229 -e SECRET=bestkeptsecret22222 -d perfops/my-todo-list
0f5860bebdb5c70538bcdd10ddc901411b37ea0c7d92283310700085b1b8ddc5

5.您可以通过在容器id之后输入docker logs命令来检查日志:

docker logs 0f5860bebdb5c70538bcdd10ddc901411b37ea0c7d92283310700085b1b8ddc5
> My@1.0.0 start-debug /usr/src/app
> node --inspect=0.0.0.0 app.js

Debugger listening on ws://0.0.0.0:9229/59d4550c-fc0e-412e-870a-c02b4a6dcd0f
Forhelp , see: https://nodejs.org/en/docs/inspector

请注意,调试器现在正在侦听端口9229 。 接下来,将配置Visual Studio代码以调试应用程序。

使用Visual Studio代码调试应用程序

1.在Visual Studio Code中,打开MyTodoApp目录。

2.调试配置存储在名为launch.json的文件中。 要打开它,请按Command+Shift+P ,然后选择“ Debug: Open launch.json

3.用以下代码片段替换launch.json文件的内容:

{"version" : "0.2.0" ,
  "configurations" : [
      {
          "name" : "Docker: Attach to Node" ,
          "type" : "node" ,
          "request" : "attach" ,
          "port" : 9229,
          "address" : "localhost" ,
          "localRoot" : " ${workspaceFolder} " ,
          "remoteRoot" : "/usr/src/app" ,
          "protocol" : "inspector" ,
          "skipFiles" : [
            " ${workspaceFolder} /node_modules/**/*.js" ,
            "<node_internals>/**/*.js"
          ]
      }
  ]
}

请注意,我们使用skipFiles属性来避免单步执行node_modules目录和Node.js的内置核心模块中的代码。

4.现在一切都已设置好,您可以开始调试应用程序了。 请记住, views.js文件的第15行有一个错误,该错误基本上遍历了todolist数组: todolist.forEach(function(todo, index) 。查看app.js文件,您会看到todo.ejs在第14行渲染。让我们添加一个断点,以便我们可以检查todolist变量的值:

5.输入Shift+Command+D切换到“ Debug视图。 然后,单击“ Debug and Run按钮:

6.要检查req.session.todolist变量的值,必须通过选择+号然后键入变量的名称( req.session.todolist )添加一个新的表达式以进行观察:

7.切换到浏览器窗口,然后重新加载http:// localhost:3001页面。

请注意底部的“ Waiting for localhost消息。 这意味着我们的断点已暂停执行,我们可以检查req.session.todolist变量的值。 返回到Visual Studio以获取详细信息:

因此, req.session.todolist变量是undefined 。 您能想到如何解决此错误吗? 答案在下面,但是请先考虑一下再继续。

8. ejb模板遍历应存储在当前会话中的todolist数组。 但是我们忘了初始化这个数组,所以它是undefined 。 让我们通过在.use函数中添加以下代码行来解决此问题:

if (typeof (req.session.todolist) == 'undefined' ) {
    req.session.todolist = []
}

确保将此代码段粘贴在调用下一个函数的代码行上方。 您的.use函数应如下所示:

app.use(session({ secret: process.env.SECRET }))
  .use(function (req, res, next) {
    if (typeof (req.session.todolist) == 'undefined' ) {
      req.session.todolist = []
    }
    next()
  })

9.检索正在运行的容器的id

docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                            NAMES
cb9f175f7af3        prospectone/my-todo-list"docker-entrypoint.s…"   15 minutes ago      Up 15 minutes       0.0.0.0:9229->9229/tcp, 0.0.0.0:3001->3000/tcp   nervous_hopper

10.通过输入docker kill命令和其id停止容器:

dockerkill cb9f175f7af3
cb9f175f7af3

11.要应用更改,您必须再次运行docker build命令:

docker build -t prospectone/my-todo-list .
Sending build context to Docker daemon  26.11kB
Step 1/7 : FROM node:10
 ---> c5d0d6dc0b5b
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 508b797a892e
Step 3/7 : COPY package*.json ./
 ---> Using cache
 ---> c5ac875da76b
Step 4/7 : RUN npm install
 ---> Using cache
 ---> 29e7b3bac403
Step 5/7 : COPY . .
 ---> b92f577afd57
Step 6/7 : EXPOSE 3000
 ---> Runningin 78606a3c2e03
Removing intermediate container 78606a3c2e03
 ---> 59c2ed552549
Step 7/7 : CMD [ "npm" , "run" , "start-debug" ]
 ---> Running in e0313973bb5a
Removing intermediate container e0313973bb5a
 ---> 70a675646c0d
Successfully built 70a675646c0d
Successfully tagged prospectone/my-todo-list:latest

12.现在,您可以使用以下命令运行容器:

docker run -p 3001:3000 -p 9229:9229 -e SECRET=bestkeptsecret222212 -d prospectone/my-todo-list
f75d4ef8b702df13749b10615f3945ea61b36571b0dc42b76f50b3c99e14f4c6

13.通过运行以下命令来检查日志:

docker logs 10f467dbb476
f75d4ef8b702df13749b10615f3945ea61b36571b0dc42b76f50b3c99e14f4c6

14.重新加载页面并添加新任务:

恭喜,您已经成功编写了一个基本的待办事项应用程序,并在Docker容器中运行了该应用程序,并使用Visual Studio Code对其进行了调试并修复了一个错误。 在下一篇博客文章中,我们将引导您完成对现有应用程序进行docker化的过程。

关于作者-Sudip是一位具有15年以上工作经验的解决方案架构师,并且是Javelynn的创始人。 他喜欢通过写作分享自己的知识,当他不这样做时,他一定是在钓鱼或下棋。

先前发布在 https://appfleet.com/上

翻译自: https://hackernoon.com/14-steps-to-debugging-a-nodejs-application-running-in-a-docker-container-s52q3ydx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值