Как использовать Node.js с Docker – CodesCode
Узнайте о преимуществах запуска приложений Node.js в контейнерах Docker и создание практического рабочего процесса для разработки.
Этот учебник объясняет преимущества запуска приложений Node.js в контейнерах Docker и показывает, как создать практический рабочий процесс разработки.
Node.js позволяет создавать быстрые и масштабируемые веб-приложения с использованием JavaScript как на сервере, так и на клиенте. Ваше приложение может работать отлично на вашей рабочей машине, но можете ли вы быть уверены, что оно будет работать на устройствах ваших коллег или на производственных серверах?
Рассмотрим следующие сценарии:
- Возможно, вы используете macOS, когда другие используют Windows, а сервер работает на Linux.
- У вас установлена версия Node.js 20, но другие используют другие версии выполнения времени.
- Вы используете зависимости, такие как базы данных, которые имеют различия или могут быть недоступны на других платформах.
- Вы уверены, что ваш новый код не может нанести вред на другой операционной системе (ОС)?
- Docker поставляет
- Ваш первый скрипт
- Запуск сложных приложений
- Лучший рабочий процесс разработки Docker
- Резюме
Docker поставляет
Docker помогает решить проблемы “это работает на моей машине” из перечисленных выше. Вместо установки приложения локально, вы запускаете его в легкой изолированной виртуальной машине-подобной среде, известной как контейнер.
Настоящая виртуальная машина эмулирует аппаратное обеспечение ПК, чтобы вы могли установить ОС. Docker эмулирует ОС, чтобы вы могли устанавливать приложения. Обычно устанавливается одно приложение на контейнере на основе Linux и они соединяются через виртуальную сеть для общения по порту HTTP.
Преимущества:
- Ваша установка Docker может эмулировать производственный сервер Linux или вы можете развернуть его с помощью контейнеров.
- Вы можете загружать, устанавливать и настраивать зависимости за несколько минут.
- Ваше контейнеризованное приложение работает идентично на всех устройствах.
- Это безопаснее. Ваше приложение может испортить ОС контейнера, но это не повлияет на ваш компьютер, и вы можете перезапустить его с чистого листа за секунды.
С Docker вам не нужно устанавливать Node.js на свой компьютер или использовать такую возможность управления временем выполнения, как nvm.
Ваш первый скрипт
Установите Docker Desktop на Windows, macOS или Linux, а затем создайте небольшой скрипт с именем version.js
с следующим кодом:
console.log(`Версия Node.js: ${ process.version }`);
Если у вас установлен Node.js локально, попробуйте выполнить этот скрипт. Вы увидите следующий вывод, если у вас установлена версия 18:
$ node version.jsВерсия Node.js: v18.18.2
Теперь вы можете запустить тот же скрипт внутри контейнера Docker. Ниже приведена команда, которая использует самую свежую версию долгосрочной поддержки (LTS) Node.js. Перейдите в каталог со скриптом и выполните его в macOS или Linux:
$ docker run --rm --name version \ -v $PWD:/home/node/app \ -w /home/node/app \ node:lts-alpine version.jsВерсия Node.js: v20.9.0
Пользователи Windows Powershell могут использовать аналогичную команду с фигурными скобками вокруг PWD
:
> docker run --rm --name version -v ${PWD}:/home/node/app -w /home/node/app node:lts-alpine version.jsВерсия Node.js: v20.9.0
Первый запуск может занять минуту или две, так как Docker загружает зависимости. Последующие запуски мгновенны.
Давайте попробуем другую версию Node, например, последнюю версию 21. На macOS или Linux:
$ docker run --rm --name version \ -v $PWD:/home/node/app \ -w /home/node/app \ node:21-alpine version.jsNode.js version: v21.1.0
В Windows Powershell:
> docker run --rm --name version -v ${PWD}:/home/node/app -w /home/node/app node:21-alpine version.jsNode.js version: v21.1.0
Помните, что скрипт выполняется внутри контейнера Linux, в котором установлена определенная версия Node.js.
Объяснение аргументов
Для любопытных, аргументы команды:
-
docker run
запускает новый контейнер из образа – об этом позже. -
--rm
удаляет контейнер при завершении. Нет необходимости сохранять контейнеры, если у вас нет оснований перезапустить их снова. -
--name version
присваивает имя контейнеру для более простого управления. -
-v $PWD:/home/node/app
(или-v ${PWD}:/home/node/app
) связывает том. В данном случае, текущий каталог на хост-компьютере смонтирован внутри контейнера в пути/home/node/app
. -
-w /home/node/app
устанавливает рабочий каталог Node.js. -
node:lts-alpine
– это образ, в данном случае, LTS-версия Node.js, работающая на Alpine Linux. Образ содержит ОС и файлы, необходимые для выполнения приложения. Представьте его как снимок диска. Вы можете запустить любое количество контейнеров из одного и того же образа: все они ссылаются на один и тот же набор файлов, поэтому каждый контейнер требует минимальных ресурсов. -
version.js
– это команда для выполнения (из рабочего каталога).
Образы Docker доступны на Docker Hub и они доступны для приложений и сред выполнения, включая Node.js. Обычно образы доступны в разных версиях, которые идентифицируются с помощью тега, такого как :lts-alpine
, 20-bullseye-slim
или просто latest
.
Обратите внимание, что Alpine – это крошечное распространение Linux с размером базового образа около 5 МБ. В нем нет многих библиотек, но для простых проектов, таких как в этом учебнике, это вполне достаточно.
Запуск сложных приложений
Скрипт version.js
выше простой и не содержит зависимостей или шагов сборки. Большинство приложений Node.js используют npm
для установки и управления модулями в каталоге node_modules
. Вы не можете использовать вышеуказанную команду, потому что:
- Вы не можете запустить
npm
на хост-компьютере (у вас может не быть установленного Node.js или правильной версии). - Некоторые модули требуют платформозависимых бинарных файлов. Вы не можете установить Windows-бинарник на хост-компьютер и ожидать, что он будет работать в контейнере Linux.
Решение – создать свой собственный образ Docker, который содержит:
- соответствующую версию исполняемой среды Node.js
- установленную версию вашего приложения со всеми необходимыми модулями
Демонстрация ниже создает простое приложение Node.js с использованием фреймворка Express.js. Создайте новый каталог с именем simple
и добавьте файл package.json
со следующим содержимым:
{ "name": "simple", "version": "1.0.0", "description": "пример простого приложения Node.js с использованием Docker", "type": "module", "main": "index.js", "scripts": { "debug": "node --watch --inspect=0.0.0.0:9229 index.js", "start": "node index.js" }, "license": "MIT", "dependencies": { "express": "^4.18.2" }}
Добавьте файл index.js
с JavaScript кодом:
// Приложение Express
import express from 'express';
// Конфигурация
const cfg = {
port: process.env.PORT || 3000
};
// Инициализация Express
const app = express();
// Маршрут главной страницы
app.get('/:name?', (req, res) => {
res.send(`Привет ${req.params.name || 'Мир'}!`);
});
// Запуск сервера
app.listen(cfg.port, () => {
console.log(`Сервер работает на http://localhost:${cfg.port}`);
});
Не пытайтесь устанавливать зависимости или запустить это приложение на компьютере хоста!
Создайте файл с именем Dockerfile
со следующим содержимым:
# Базовый образ Node.js LTS
FROM node:lts-alpine
# Определение переменных среды
ENV HOME=/home/node/app
ENV NODE_ENV=production
ENV NODE_PORT=3000
# Создание папки приложения и назначение прав пользователю node
RUN mkdir -p $HOME && chown -R node:node $HOME
# Установка рабочей директории
WORKDIR $HOME
# Задание активного пользователя
USER node
# Копирование package.json с хоста
COPY --chown=node:node package.json $HOME/
# Установка модулей приложения
RUN npm install && npm cache clean --force
# Копирование оставшихся файлов
COPY --chown=node:node . .
# Открытие порта на хосте
EXPOSE $NODE_PORT
# Команда запуска приложения
CMD [ "node", "./index.js" ]
В этом файле описаны шаги, необходимые для установки и запуска вашего приложения. Обратите внимание, что файл package.json
копируется в образ, затем выполняется команда npm install
, после чего копируются остальные файлы. Это более эффективно, чем копирование всех файлов сразу, потому что Docker создает слой образа при каждой команде. Если изменяются файлы вашего приложения (index.js
), Docker должен выполнить только последние три шага; ему не нужно заново выполнять команду npm install
.
При желании вы можете добавить файл .dockerignore
. Он похож на .gitignore
и предотвращает копирование ненужных файлов в образ с помощью команды COPY . .
. Например:
Dockerfile.git.gitignore.vscodenode_modulesREADME.md
Создайте Docker-образ с именем simple
, выполнив следующую команду (обратите внимание на точку .
в конце — она указывает, что вы используете файлы из текущего каталога):
$ docker image build -t simple .
Если образ node:lts-alpine
Docker, использованный выше, не был удален с вашей системы, образ должен собраться за несколько секунд.
Предполагая, что сборка прошла успешно, запустите контейнер из вашего образа:
$ docker run -it --rm --name simple -p 3000:3000 simple
Сервер работает на http://localhost:3000
Флаг -p 3000:3000
открывает <хост-порт>
для <порт-контейнера>
, поэтому порт 3000 на вашем компьютере маршрутизируется на порт 3000 внутри контейнера.
Откройте браузер и введите URL http://localhost:3000/
, чтобы увидеть “Привет, Мир!”
Попробуйте добавить имена в URL, например http://localhost:3000/Craig
, чтобы увидеть альтернативные сообщения.
Наконец, остановите работу вашего приложения, нажав на значок stop во вкладке Containers в Docker Desktop, или выполните следующую команду в другом окне терминала:
docker container stop simple
Более эффективный рабочий процесс Docker для разработки
Процесс, описанный выше, имеет несколько недостатков:
-
Любое изменение вашего кода (в файле
index.js
) требует остановки контейнера, пересборки образа, перезапуска контейнера и повторного тестирования. -
Вы не можете подключить отладчик Node.js, такой как отладчик доступный в VS Code.
Docker может улучшить ваш рабочий процесс разработки, сохраняя существующий образ для производственного использования, но запуская контейнер с переопределениями для выполнения следующих действий:
-
Установка переменных среды, таких как
NODE_ENV=development
. -
Примонтирование локального каталога в контейнер.
-
Запуск приложения с помощью
npm run debug
. Это запускаетnode --watch --inspect=0.0.0.0:9229 index.js
, который перезапускает приложение при изменении файлов (новое в Node.js 18) и запускает отладчик с внешними запросами разрешенными из контейнера. -
Открытие порта приложения 3000 и порта отладки 9229 на хосте.
Вы можете сделать это одной длинной командой docker run
, но я предпочитаю использовать Docker Compose. Он устанавливается вместе с Docker Desktop и часто используется для запуска нескольких контейнеров. Создайте новый файл с именем docker-compose.yml
со следующим содержимым:
version: '3'services: simple: environment: - NODE_ENV=development build: context: ./ dockerfile: Dockerfile container_name: simple volumes: - ./:/home/node/app ports: - "3000:3000" - "9229:9229" command: /bin/sh -c 'npm install && npm run debug'
Запустите ваше приложение в режиме отладки с помощью команды:
$ docker compose up[+] Building 0.0s[+] Running 2/2 ✔ Network simple_default Created ✔ Container simple CreatedAttaching to simplesimple |simple | up to date, audited 63 packages in 481mssimple |simple | > [email protected] debugsimple | > node --watch --inspect=0.0.0.0:9229 index.jssimple |simple | Debugger listening on ws://0.0.0.0:9229/de201ceb-5d00-1234-8692-8916f5969cbasimple | Справка: https://nodejs.org/en/docs/inspectorsimple | Сервер слушает на http://localhost:3000
Обратите внимание, что в старых версиях Docker Compose это были сценарии Python, запускаемые с помощью docker-compose
. В новых версиях функциональность Compose интегрирована в основное исполняемое приложение, поэтому оно запускается с помощью docker compose
.
Перезапуск приложения в режиме реального времени
Откройте файл index.js
, внесите изменение (например, поменяйте строку на 14-й строке) и сохраните файл, чтобы увидеть автоматический перезапуск приложения:
simple | Перезапуск 'index.js'simple | Debugger listening on ws://0.0.0.0:9229/acd16665-1399-4dbc-881a-8855ddf9d34csimple | Справка: https://nodejs.org/en/docs/inspectorsimple | Сервер слушает на http://localhost:3000
Откройте или обновите ваш браузер по адресу https://localhost:3000/
, чтобы увидеть обновления.
Отладка с помощью VS Code
Откройте панель Запуск и отладка в VS Code и нажмите создать файл launch.json.
Выберите Node.js в выпадающем списке, и будет создан и открыт в редакторе файл .vscode/launch.json
. Добавьте следующий код, который подключает отладчик к запущенному контейнеру:
{
// Используйте IntelliSense, чтобы узнать о возможных атрибутах.
// Наведите указатель, чтобы увидеть описания существующих атрибутов.
// Дополнительную информацию можно найти по адресу: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach to Container",
"address": "localhost",
"port": 9229,
"localRoot": "${workspaceFolder}",
"remoteRoot": "/home/node/app",
"skipFiles": [
"<node_internals>/**"
]
}
]
}
Сохраните файл, затем нажмите Подключиться к контейнеру в верхней части панели отладки, чтобы начать отладку.
Появится панель отладки. Перейдите к файлу index.js
и установите точку останова на 14-й строке, нажав на левый край окна рядом с текстом кода.
Обновите браузер по адресу https://localhost:3000/
, и VS Code приостановит выполнение кода на точке останова и покажет состояние всех переменных приложения. Щелкните по значкам на панели отладки, чтобы продолжить выполнение, пошагово пройти по коду или отключить отладчик.
Остановить контейнер
Остановите работающий контейнер, открыв другой терминал. cd
в директорию приложения и выполните команду:
docker compose down
Сводка
Хотя Docker требует некоторого времени на первоначальную настройку, долгосрочные преимущества надежного и распределенного кода более чем оправдывают затраченные усилия. Docker становится бесценным, когда добавляются дополнительные зависимости, такие как базы данных.
Это руководство объясняет основы запуска приложений Node.js в контейнерах Docker. Если вы хотите углубиться в тему, рассмотрите эти ресурсы CodesCode:
-
Книга: Docker для веб-разработчиков
-
Видеокурс: Docker для веб-разработчиков
-
Курс и видео: Node.js: с нуля до эксперта. Главы с 13 по 16 демонстрируют, как создать масштабируемое приложение для викторин в реальном времени с использованием Docker для запуска сети, содержащей два сервера Node.js Express, три сервера Node.js Web Socket, базу данных PostgreSQL и балансировщик нагрузки.
Leave a Reply