Movatterモバイル変換


[0]ホーム

URL:


Version 1.107 is now available! Read about the new features and fixes from November.

Dismiss this update

Debug Node.js within a container

When adding Docker files to a Node.js project, tasks and launch configurations are added to enable debugging that application within a container. However, due to the large ecosystem surrounding Node.js, those tasks cannot accommodate every application framework or library, which means that some applications will require additional configuration.

Configuring the container entry point

The Container Tools extension infers the entry point of the container--that is, the command line for starting the application in a debug mode within the container--via properties ofpackage.json. The extension first looks for thestart script in thescripts object; if found and, if it starts with anode ornodejs command, it uses that to build the command line for starting the application in debug mode. If not found or, if not a recognizednode command, themain property in thepackage.json is used. If neither is found or recognized, then you need to explicitly set thedockerRun.command property of thedocker-run task used to start the container.

Some Node.js application frameworks include CLIs for managing the application and are used to start the application in thestart script, which obscure the underlyingnode commands. In these cases, the Container Tools extension cannot infer the start command and you must explicitly configure the start command.

Example: Configuring the entry point for aNest.js application

{  "tasks": [    {      "type":"docker-run",      "label":"docker-run: debug",      "dependsOn": ["docker-build"],      "dockerRun": {        "command":"nest start --debug 0.0.0.0:9229"      },      "node": {        "enableDebugging":true      }    }  ]}

Example: Configuring the entry point for aMeteor application

{  "tasks": [    {      "type":"docker-run",      "label":"docker-run: debug",      "dependsOn": ["docker-build"],      "dockerRun": {        "command":"node --inspect=0.0.0.0:9229 main.js"      },      "node": {        "enableDebugging":true      }    }  ]}

Automatically launching the browser to the entry page of the application

The Container Tools extension can automatically launch the browser to the entry point of the application after it has started in the debugger. This feature is enabled by default and configured via thedockerServerReadyAction object of the debug configuration inlaunch.json.

This feature depends on several aspects of the application:

  • The application must output logs to the debug console.
  • The application must log a "server ready" message.
  • The application must serve a browsable page.

While the default settings may work for an Express.js based application, other Node.js frameworks may require explicit configuration of one or more of those aspects.

Ensuring application logs are written to the debug console

This feature depends on the application writing its logs to the debug console of the attached debugger. However, not all logging frameworks write to the debug console, even when configured to use a console-based logger (as some "console" loggers actually bypass the console and write directly tostdout).

The solution varies depending on the logging framework, but it generally requires creating/adding a logger thatactually writes to the console.

Example: Configuring Express applications to write to the debug console

By default,Express.js uses thedebug logging module, which can bypass the console. This can be resolved by explicitly binding the log function to the console'sdebug() method.

var app =require('../app');var debug =require('debug')('my-express-app:server');var http =require('http');// Force logging to the debug console.debug.log =console.debug.bind(console);

Also note that thedebug logger writes logs only when enabled via theDEBUG environment variable, which can be set in thedocker-run task. (This environment variable is set to* by default when Docker files are added to the application.)

{  "tasks": [    {      "type":"docker-run",      "label":"docker-run: debug",      "dependsOn": ["docker-build"],      "dockerRun": {        "env": {          "DEBUG":"*"        }      },      "node": {        "enableDebugging":true      }    }  ]}

Configuring when the application is "ready"

The extension determines the application is "ready" to receive HTTP connections when it writes a message of the formListening on port <number> to the debug console, as Express.js does by default. If the application logs a different message, then you should set thepattern property of thedockerServerReadyAction object of the debug launch configuration to aJavaScript regular expression that matches that message. The regular expression should include a capture group that corresponds to the port on which the application is listening.

For example, suppose the application logs the following message:

function onListening() {  var addr =server.address();  var bind =typeof addr ==='string' ?'pipe ' +addr :'port ' +addr.port;  debug('Application has started on ' +bind);}

The correspondingpattern in the debug launch configuration (inlaunch.json) is:

{  "configurations": [    {      "name":"Containers: Node.js Launch",      "type":"docker",      "request":"launch",      "preLaunchTask":"docker-run: debug",      "platform":"node",      "dockerServerReadyAction": {        "pattern":"Application has started on port (\\d+)"      }    }  ]}

Note the(\\d+) capture group for the port number, and the use of\ as a JSON escape character for the backslash in the\d character class.

Configuring the application entry page

By default, the Container Tools extension will open the "main" page of the browser (however that is determined by the application). If the browser should be opened to a specific page, theuriFormat property of thedockerServerReadyAction object of the debug launch configuration should be set to a Node.js format string, with one string token that indicates where the port should be substituted.

The correspondinguriFormat in the debug launch configuration (inlaunch.json) to open theabout.html page instead of the main page would be:

{  "configurations": [    {      "name":"Containers: Node.js Launch",      "type":"docker",      "request":"launch",      "preLaunchTask":"docker-run: debug",      "platform":"node",      "dockerServerReadyAction": {        "uriFormat":"http://localhost:%s/about.html"      }    }  ]}

Mapping container source files to the local workspace

By default, the Container Tools extension assumes the application source files in the running container are located in an/usr/src/app folder, and the debugger then maps those files back to the root of the opened workspace, in order to translate breakpoints from the container back to Visual Studio Code.

If the application source files are in a different location (for example, different Node.js frameworks have different conventions), either within the container or within the opened workspace, then one or both of thelocalRoot andremoteRoot properties of thenode object of the debug launch configuration should be set the root source locations within the workspace and the container, respectively.

For example, if the application instead resides in/usr/my-custom-location, the correspondingremoteRoot property would be:

{  "configurations": [    {      "name":"Containers: Node.js Launch",      "type":"docker",      "request":"launch",      "preLaunchTask":"docker-run: debug",      "platform":"node",      "node": {        "remoteRoot":"/usr/my-custom-location"      }    }  ]}

Troubleshooting

Container image fails to build or start due to missing node_modules

Dockerfiles are often arranged in such a way as to optimize either image build time, image size, or both. However, not every Node.js application framework supports all of the typical Node.js Dockerfile optimizations. In particular, for some frameworks, thenode_modules folder must be an immediate subfolder of the application root folder, whereas, the Container Tools extension scaffolds a Dockerfile where thenode_modules folder exists at a parent or ancestor level (which is generally allowed by Node.js).

The solution is to remove that optimization from theDockerfile:

FROM node:lts-alpineENV NODE_ENV=productionWORKDIR /usr/src/appCOPY ["package.json","package-lock.json*","npm-shrinkwrap.json*","./"]# Remove the `&& mv node_modules ../` from the RUN command:# RUN npm install --production --silent && mv node_modules ../RUN npm install --production --silentCOPY . .EXPOSE 3000RUN chown -R node /usr/src/appUSER nodeCMD ["npm","start"]
12/21/2022

    [8]ページ先頭

    ©2009-2025 Movatter.jp