Как докеризировать веб-приложение Node.js — CloudSavvy IT

Docker — это платформа контейнеризации, которая упрощает упаковку и выполнение приложений. Контейнеры работают как изолированные процессы со своей собственной файловой системой, но совместно используют ядро ​​своего хоста. Docker приобрел известность как способ реализации воспроизводимых сред разработки и архитектур распределенного развертывания.

Node.js — ведущая среда выполнения JavaScript для серверной разработки. Для успешного запуска веб-службы Node.js требуется среда с установленной средой выполнения, доступный код приложения и механизм, который обрабатывает автоматические перезапуски в случае сбоя.

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

Создание вашего проекта узла

Мы пропустим детали реализации вашего приложения. Создайте каталог для своего проекта и добавьте в него код сервера. Вот базовый app.js, который прослушивает порт 8080 и отвечает на каждый запрос жестко заданным ответом:

константный экспресс = требуется («экспресс»); константное приложение = экспресс(); app.get(«*», (req, res) => res.send(«

Это работает!

«)); app.listen(8080, () => console.log(«Прослушивание 8080»));

Добавьте Express в свой проект с помощью npm:

npm init npm install —save экспресс

Запустите приложение, чтобы проверить его работу:

узел app.js

Вы должны иметь возможность посетить localhost:8080 в своем браузере, чтобы увидеть образец ответа.

Написание Dockerfile

Теперь пришло время приступить к докеризации вашего проекта. Сначала вам нужно изображение для вашего приложения. Образы инкапсулируют ваш код и зависимости в виде единого пакета, который вы используете для запуска экземпляров контейнера. Инструкции в вашем Dockerfile определяют состояние исходной файловой системы ваших контейнеров.

Вот Dockerfile, который работает для примера приложения:

ИЗ node:16 WORKDIR /app COPY package.json . КОПИРОВАТЬ package-lock.json . ЗАПУСТИТЬ npm ci КОПИРОВАТЬ app.js . CMD [«app.js»]

Этот Dockerfile выбирает официальный образ Node.js Docker в качестве основы с помощью оператора FROM. Образ наследует все в базе, а затем добавляет дополнительный контент с помощью следующих инструкций.

Рабочий каталог устанавливается в /app строкой WORKDIR. Следующие операторы COPY помещают файлы в каталог /app внутри образа контейнера.

Установка зависимостей

Следующий этап — добавить package.json npm и запустить npm ci. Это установит зависимости npm вашего проекта — в данном случае Express — в файловой системе контейнера.

Не используйте COPY node_modules/ . чтобы скопировать существующую папку node_modules в каталог вашего проекта — это помешает вам повторно использовать файл Dockerfile в других средах сборки. Файлы Docker должны позволить вам создавать согласованные сборки только с содержимым вашего репозитория системы управления версиями. Если файл или папка находятся в вашем .gitignore, на них не следует ссылаться в инструкции Dockerfile COPY.

Копирование кода приложения

После запуска npm ci код вашего приложения копируется в образ. Размещение этой инструкции COPY после RUN, отделяя ее от предыдущих копий, является преднамеренным. Каждая инструкция создает новый слой в вашем изображении; Процесс сборки Docker кэширует каждый уровень для ускорения последующих сборок. Как только содержимое одного слоя изменится, кэш всех последующих слоев станет недействительным.

Вот почему код приложения следует копировать после выполнения npm ci. Код обычно меняется гораздо чаще, чем содержимое вашего файла блокировки npm. Перестроение образа, которое включает только изменения кода, эффективно пропускает этап RUN npm ci (и все более ранние этапы), значительно ускоряя процесс, когда у вас много зависимостей.

Установка команды изображения

На последнем этапе Dockerfile используется инструкция CMD для автоматического запуска вашего приложения при запуске контейнера. Это работает, потому что базовый образ Node.js настроен на использование процесса узла в качестве точки входа. CMD добавляется к унаследованной точке входа, в результате чего узел app.js запускается как процесс переднего плана для вашего нового образа.

Создание вашего имиджа

Далее вам нужно создать свой образ:

docker build -t node-app:latest .

Docker возьмет Dockerfile в вашем рабочем каталоге, запустит в нем инструкции и пометит полученный образ как node-app:latest. Финал . (точка) указывает ваш рабочий каталог в качестве контекста сборки образа. Это определяет пути, на которые могут ссылаться инструкции COPY в вашем Dockerfile.

Оптимизация сборки

Один из способов повысить производительность сборки — добавить файл .dockerignore в корень вашего проекта. Дайте файлу следующее содержимое:

node_modules/

Этот файл определяет пути в вашем рабочем каталоге, которые будут нет быть включенным в контекст сборки. Вы не сможете ссылаться на них внутри своего Dockerfile. В случае node_modules содержимое этого каталога не имеет отношения к сборке, поскольку мы устанавливаем зависимости заново с помощью инструкции RUN npm ci. В частности, исключение node_modules, уже присутствующих в вашем рабочем каталоге, избавляет от необходимости копировать все эти файлы во временное расположение контекста сборки Docker. Это повышает эффективность и сокращает время, затрачиваемое на подготовку сборки.

Запуск контейнера

На данный момент вы готовы запустить свое приложение с помощью Docker:

docker run -d \ -p 8080:8080 \ —name my-app \ —restart on-failure \ node-app:latest

Команда docker run используется для запуска нового экземпляра контейнера из указанного образа. Добавлено несколько дополнительных флагов для правильной настройки контейнера для предполагаемого варианта использования:

  • -d — отсоединяет вашу оболочку от процесса переднего плана контейнера, эффективно запуская его в качестве фонового сервера.
  • -p — привязывает порт 8080 на вашем хосте к порту 8080 внутри контейнера (который наш пример приложения Express был настроен для прослушивания). Это означает, что трафик на localhost:8080 будет проходить через соответствующий порт контейнера. Вы можете изменить запись хоста на другое значение, изменив первую часть определения привязки, например 8100:8080, чтобы получить доступ к вашему контейнеру на локальном хосте:8100.
  • —name — присваивает контейнеру понятное имя, которое вы можете использовать для ссылки на него в других командах Docker CLI.
  • —restart — выбирает политику перезапуска для применения к контейнеру. Настройка при сбое означает, что Docker автоматически перезапустит контейнер, если он выйдет с кодом сбоя из-за сбоя вашего приложения.

Образ, созданный на предыдущем шаге, упоминается как последний аргумент команды запуска docker. Идентификатор контейнера будет отправлен в окно вашего терминала; вы сможете получить доступ к своему приложению Node.js, снова посетив localhost:8080. На этот раз сервер работает внутри контейнера Docker, а не использует процесс node, установленный на вашем хосте.

Резюме

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

Когда вы внесли изменения в код и хотите запустить обновление, перестройте образ Docker и удалите старый контейнер с помощью docker rm . Затем вы можете запустить заменяющий экземпляр, который использует измененный образ.

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

Эти механизмы избавляют от необходимости повторять флаги запуска докера каждый раз, когда вы запускаете новый контейнер. Они также упрощают репликацию контейнеров для масштабирования службы и обеспечения избыточности. Если вы выполняете развертывание на удаленном хосте, вам также потребуется отправить образ в реестр Docker, чтобы его можно было «извлечь» с вашей производственной машины.

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

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован.