Отладка Node.js приложения в докер-контейнере

В этой статье хочу рассказать как  настроить отладку Node.js приложения работающего в Docker-контейнере. В большинстве случаев нет никакой проблемы, чтобы отладить приложение локально, но некоторые дефекты в работе приложения проявляются только будучи запущенными в рамках контейнера. В такой ситуации гораздо эффективнее и быстрее обнаружить и исправить проблему если подключить полноценный отладчик. 

Весть процесс, с большего, состоит из 3-х шагов.

  1. Надо изменить запуск Node.js, чтобы он работал с включенным режимом отладки.
  2. Открыть доступ к порту, указанному при включении режима отладки в Node.js.
  3. Настроить инструмент для отладки. Это может быть любая IDE. Многие разработчики пользуются VS Code, я им тоже пользуюсь, на его примере я и покажу в этой статье как это сделать.
Если тексту с картинками вы предпочитаете видео, то вот мой обзор отладки Node.js приложения в докер-контейнере на YouTube

 

Я этого примера создал простое Node.js приложение и докер-файл для него. Полный пример Node.js приложения и Dockerfile к нему можно посмотреть в репозитории на GitHub.

const express = require("express");
const app = new express();

app.get("/", function(req, res){
res.send("Hello, World!");
});

const PORT = 8080;
app.listen(PORT, function(){
console.log("Listening on port " + PORT);
});

app.js

FROM node:14-alpine

WORKDIR /node-app

COPY package.json .
RUN npm install
RUN mv /node-app/node_modules /node_modules

COPY . .

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

EXPOSE 8080

Dockerfile

Шаг 1. Запускаем NodeJS в режиме отладки

Первое что надо сделать - это запустить Node.js в докер-контейнере в режиме отладки. Делается это передачей ключа --inspect при старте Node (вот здесь можно почитать подробнее). В Dockerfile у нас уже есть инструкция по запуску Node и переопределить настройки запуска Nods в контейнере можно разными способами - например, параметрами команды docker container run или можно создать файл для docker-compose и там переопределить ряд параметров. Вариант с docker-compose мне кажется более удобным.

version: '3.4'

services:
nodeapp:
build: .
ports:
- 8080:8080
command: node --inspect=0.0.0.0:9229 app.js
docker-compose.yml (not finished)


Шаг 2. Открываем доступ к порту

Теперь, дополнительно к порту на котором работает приложение нам надо открыть доступ к порту через который работает инспектор. Для этого обновляем docker-compose файл, чтобы открыть доступ к порту 9229, который мы указали в параметрах инспектора.

Зачастую так же удобно переопределить и путь к коду Node.js приложения, чтобы можно было внести изменения в код и убедиться, что приложение работает так как ожидается. Финальная версия docker-compose файла так же находится в репозитории на GitHub.

version: '3.4'

services:
nodeapp:
build: .
ports:
- 8080:8080
- 9229:9229
volumes:
- .:/node-app
command: node --inspect=0.0.0.0:9229 app.js

docker-compose.yml (final)

Запускаем docker-compose с флагом  --build :
docker-compose up --build

Шаг 3. Настраиваем VS Code и запускаем отладку

Теперь подключаем VS Code. Для этого надо добавить конфигурацию отладки в VS Code.
Для  начала надо перейти на панель отладки в VS Code
Далее, если launch.json есть, то надо добавить новую конфигурацию, 
Если launch.json еще не был создан, то его надо создать, кликнув на линку "create a launch.json file"

В появившемся списке шаблонов конфигураций можно выбрать "Node.js: Attach to Remote Program" а если такой нет, то любую и заменить ее на мой пример (файл на GitHub).

{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}",
"name": "Attach to Remote",
"port": 9229,
"remoteRoot": "/node-app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
}


На что здесь важно  обратить внимание
  • address - IP-адрес машины где запущен докер-контейнер. 
  • port - порт через который работает Node Inspector. Он должен быть такой же как мы указывали в ключе --inspect.
  • remoteRoot - путь в докер-контейнере, где находится код приложения.
Теперь можно запускать отладчик. Для этого нужно нажать кнопку "Start Debugging". 


В коде приложения можно ставить точки останова (breakpoints), проверять значения переменных и  полей объектов и пр.

Что можно сделать еще

Если пойти дальше и модифицировать немного Dockerfile можно с эпизодической отладки приложения перейти на полноценную разработку в Docker-контейнере. Это может быть удобно в случае когда надо разрабатывать и поддерживать приложения на разных версиях Node.js. Для этого нужно установить в docker-контейнер forever или любое другое приложение, которое  будет перезапускать Node при изменении кода и соответственно у нас немного изменится команда для запуска приложения. Новый докер-файл (я его назвал Dockerfile.dev) и docker-compose.dev.yml будут выглядеть так. 

FROM node:14-alpine

WORKDIR /node-app

RUN npm install -g forever

COPY package.json .
RUN npm install
RUN mv /node-app/node_modules /node_modules

COPY . .

CMD [ "forever", "-w", "app.js" ]

EXPOSE 8080

Dockerfile.dev


version: '3.4'

services:
nodeapp:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- 8080:8080
- 9229:9229
volumes:
- .:/node-app
command: forever -w -c "node --inspect=0.0.0.0:9229" app.js

docker-compose.dev.yml

Поскольку у нового docker-compose файла имя отличное от дефолтного, то запускать его надо с немного другой командой

docker-compose -f docker-compose.dev.yml up --build


Комментарии

Популярные сообщения из этого блога

Команды docker save/load, docker export/import – в чем отличие, как и когда ими пользоваться

Как "заглянуть" внутрь запущенного докер-контейнера

Как узнать, кто заблокировал файл или папку