Debugging a ES6 Node.js application in a Docker container using Visual Studio Code

Written on April 08, 2016

Yesterday I just tried to debug an ES6 Node.js application using Visual Studio Code and noticed that I couldn't remote debug.

So I just asked on Twitter and got some replies from Erich Gamma and Andre Weinand today:

As things didn't make it into official docs until now, I'll wrap it up here in a block post.

To keep things simple, this is our Node.js application:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.status(200).send('hello world');
})

app.listen(3000);

Add a jsconfig.json into the root of the project:

{
    "compilerOptions": {
        "target": "ES6",
        "module": "commonjs"
    }
}

Create a Dockerfile:

FROM node:4.2.3

EXPOSE 3000
EXPOSE 5858
COPY . /app
WORKDIR /app

RUN cd /app; npm install
CMD ["node", "--debug=5858","index.js"]

Create a launch.json (or create it by clicking the Debug button in VS Code):

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "node",
            "request": "launch",
            "program": "${workspaceRoot}/index.js",
            "stopOnEntry": false,
            "args": [],
            "cwd": "${workspaceRoot}",
            "preLaunchTask": null,
            "runtimeExecutable": null,
            "runtimeArgs": [
                "--nolazy"
            ],
            "env": {
                "NODE_ENV": "development"
            },
            "externalConsole": false,
            "sourceMaps": false,
            "outDir": null
        },
        {
            "name": "Attach",
            "type": "node",
            "request": "attach",
            "port": 5858,
            "address": "localhost",
            "restart": false,
            "sourceMaps": false,
            "outDir": null,
            "localRoot": "${workspaceRoot}/",
            "remoteRoot": "/app/"
        }
    ]
}

The important part in the launch.json is the Attach configuration, especially the localRoot and remoteRoot properties:

As our application on the host is in /index.js, ${workspaceRoot}/ is the correct setting.

As you can see in the Dockerfile, inside the container our app runs in the /app working directory.

So I've set the remoteRoot to /app/

Next, we can build our Docker image:

$ docker build -t hellovscode .

With that finished, we can run a container based on the image with port mappings for 3000 and 5858 activated:

$ docker run -d -p 3000:3000 -p 5858:5858 hellovscode

Next start the Attach Debug configuration in VS Code:

As you can see, I have already set a breakpoint.

Now, issue a request to http://localhost:3000/ - and we're remote debugging Node.js / ES6 in Docker Container using Visual Studio Code!

If you're using Docker-Machine, make sure you're using the IP address of the Docker Machine your container are running in.

You can get the IP address of the Docker Machine using:

$ docker-machine ip <machinename>

Use this IP address in the "address" property of your VS Code Attach configuration in the launch.json.

The source code including the Visual Studio Code Workspace Settings can be found here