One of the nice things about docker is that we can use all kinds of software without cluttering up our local machine. I really like the ability to have the development environment running in a container. Here is an example where we:
- Get a Node.js development environment with all required tools and packages
- Allow remote debugging of the app in the container
- See code changes immediately reflected inside the container
The dockerfile
below gives us a container with all required tools and packages for a Node.js app. In this example we assume the ‘.’ directory contains the files needed to run the app.
FROM node:9 WORKDIR /code RUN npm install -g nodemon COPY package.json /code/package.json RUN npm install && npm ls RUN mv /code/node_modules /node_modules COPY . /code CMD ["npm", "start"]
That’s nice, but how does this provide remote debugging? and how do code changes propagate to a running container?
Two very normal aspects of docker achieve this. Firstly docker-compose.yml
overrules the CMD ["npm", "start"]
statement to start nodemon
with the --inspect=0.0.0.5858
flag. That starts the app with the debugger listening on all of the machines IP addresses. We expose port 5858 to allow remote debuggers to connect to the app in the container.
Secondly, the compose file contains a volume mapping that overrules the /code
folder in the container and points it to the directory on the local machine where you edit the code. Combined with the --watch
flag nodemon
sees any changes you make to the code and restarts the app in the container with the latest code changes.
Note: If you are running docker on Windows of the code is stored on some network share, then you must use the --legacy-watch
flag instead of --watch
The docker-compose.yml
file:
version: "2" services: app: build: . command: nodemon --inspect=0.0.0.0:5858 --watch volumes: - ./:/code ports: - "5858:5858"
Here’s a launch.json
for Visual Studio Code to attach to the container.
{ "version": "0.2.0", "configurations": [ { "name": "Attach", "type": "node", "request": "attach", "port": 5858, "address": "localhost", "restart": true, "sourceMaps": false, "outDir": null, "localRoot": "${workspaceRoot}", "remoteRoot": "/code" } ] }