Мнение о рабочем процессе разработки Docker для проектов Node.js — часть 1

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

Обзор

Цели, которые мы хотели бы достичь в этой статье блога:

  • Мы ориентируемся на среду Node.js для написания приложения на стороне сервера (например, Express, Sails или другие).
  • Разрешить локальную разработку без Docker (опционально)
  • Разрешить локальную разработку с Docker с горячим обновлением при изменении кода
  • Предоставить инструкции по созданию образов для тестирования и производства
  • Изолировать контейнерные скрипты от исходного кода, чтобы одну структуру папок можно было использовать для многих проектов.
  • Быть простым, но объяснять все шаги, чтобы можно было вносить изменения и обновления.

Этот пост разделен на две части:

  1. Как использовать рабочий процесс (этот пост!)
  2. Погружение в детали того, как работают Dockerfiles

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

Краткая терминология Docker

Для тех, кто новичок в Docker, я использую некоторые термины в этом посте и хотел бы быстро дать их определение:

Dockerfile: Файл, описывающий набор инструкций для Docker Desktop по созданию образа.

Образ: Файл, содержащий конечный результат выполнения инструкций Dockerfile после того, как Docker Desktop выполнит
сборку

Контейнер: Запущенный экземпляр вашего образа, который может выполнять код.

Этого должно быть достаточно для начала работы — давайте перейдем к рабочему процессу!

Как использовать рабочий процесс

Структура каталогов и файлы

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

Это выглядит следующим образом:

└── Main_Project_Directory/
    ├── server-code/
    │   ├── server.js
    │   ├── package.json
    │   └── ... (All your other source code files)
    ├── .gitignore
    ├── .dockerignore
    ├── Dockerfile
    ├── docker-compose.yml
    └── README.md
Вход в полноэкранный режим Выход из полноэкранного режима

Этот график сгенерирован на сайте https://tree.nathanfriend.io/.

Примечания

  • Каталог server-code — это произвольное имя.
    Вы можете переименовать его, но не забудьте обновить все ссылки в файлах Dockerfiles и командах Docker, показанных в этой статье. Цель этого подкаталога — изолировать ваш серверный код от всего рабочего процесса.

  • Файлы Dockerfile, docker-compose.yml и .dockerignore будут взяты из этого репозитория.

  • Ваше приложение должно начинаться с файла server.js, потому что при запуске контейнер будет запускать node server.js. Если вы хотите переименовать его, то вам придется обновить файлы, чтобы они ссылались на ваш собственный стартовый файл.

Установка

Вам потребуется установить Docker Desktop.

Клонируйте это репо: https://github.com/edgarroman/docker-setup-node-container или просто возьмите файлы, связанные с Docker, и создайте структуру каталогов, как показано выше.

Обновления

Со временем вы захотите изменить/обновить версии Node.js и npm. Вы можете найти версии в верхней части Dockerfile. На момент написания этой статьи строки выглядят следующим образом:

# Base node images can be found here: https://hub.docker.com/_/node?tab=description&amp%3Bpage=1&amp%3Bname=alpine
ARG NODE_IMAGE=node:16.17-alpine
Вход в полноэкранный режим Выйти из полноэкранного режима

Чтобы узнать версию Node.js, зайдите на официальный докер-хаб node и выберите свой базовый докер-образ. Я рекомендую вам остановиться на alpine, если у вас нет дополнительных потребностей. Замените 2-ю строку в Dockerfile на нужный вам тег.

Для версии npm смотрите строку 11. Обновите ее по своему усмотрению.

ARG NPM_VERSION=npm@8.18.0
Вход в полноэкранный режим Выйти из полноэкранного режима

Все остальные версии пакетов и прочее зависят от ваших предпочтений внутри вашего приложения.

Руководство по рабочим процессам

Мы рассмотрим рабочие процессы разработки и тестирования вашего кода. Существует несколько рабочих процессов, о которых мы поговорим в этом посте.

  1. Локальная разработка без контейнеров
  2. Локальная разработка с контейнерами (предпочтительно)
  3. Производственная сборка и локальное тестирование с контейнерами

Локальная разработка без контейнеров

Этот дополнительный рабочий процесс вообще не использует Docker.

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

Ваша локальная система будет напрямую запускать Node и напрямую загружать ваш код. Этот рабочий процесс требует наименьшего количества вычислительной мощности вашей машины и обеспечивает наиболее отзывчивую среду разработки. Когда вы вносите изменения в свой код, они будут отражены максимально быстро. (используя nodemon для горячей перезагрузки кода при обнаружении изменений).

Недостатком такого подхода является то, что, скорее всего, на вашей локальной машине установлена не та операционная система, на которой будет работать ваш конечный контейнер. Если вы используете Windows, MacOS или даже некоторые разновидности Linux, пакеты, используемые локально, могут быть не идентичны тем, которые в конечном итоге будут использоваться в производстве.

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

Учитывая вышеперечисленные подводные камни, почему вы должны использовать этот подход? Я бы рекомендовал этот подход только в том случае, если вы работаете в среде, где запуск Docker Desktop создает слишком большую нагрузку на вашу машину.

В целом, я рекомендую использовать следующий рабочий процесс.

Локальная разработка с контейнерами (предпочтительно)

Этот рабочий процесс позволяет вам вести разработку, запуская код в контейнерной среде. Это контейнерное окружение в точности соответствует тому, что вы будете развертывать на производстве. И вам не нужно устанавливать на локальную машину ничего, кроме Docker Desktop.

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

Ключевым преимуществом этого рабочего процесса является то, что вы можете редактировать свой исходный код, и любые обновления будут отражены в контейнере. Мы по-прежнему используем nodemon для обнаружения изменений исходного кода и перезагрузки Node. Это значительно облегчает разработку, позволяя разработчикам видеть изменения гораздо быстрее, чем необходимость пересобирать образ при каждом изменении.

Шаги для начала работы

  1. Запустите Docker Desktop на локальной машине
  2. Перейдите в основной каталог проекта (не в server-code).
  3. Если вы впервые запускаете этот рабочий процесс, или если вы изменили какие-либо зависимости пакетов, запустите его:

    docker compose build
    

    Этот шаг запустит npm install в вашем образе и зафиксирует все, что вы перечислили в package.json.

  4. Теперь выполните следующую команду, чтобы создать контейнер (запущенный экземпляр вашего образа).

    docker compose up
    
  5. Вы сможете увидеть, что ваш проект запущен по адресу http://localhost:8080/. Также вы сможете увидеть все журналы, выводимые в консоль.

  6. Нажмите Control-C, чтобы выйти из консоли и остановить контейнер. (Эквивалентно docker compose stop, если вы знакомы с командами Docker).

  7. На этом этапе ваш контейнер остановлен, но Docker на всякий случай подготовил его к повторному запуску. Если вы закончили разработку или вам нужно внести изменения в пакет, введите следующую команду, чтобы Docker Desktop выполнил полную очистку. Он удалит контейнер, но сохранит ваш образ на случай, если вы захотите запустить его снова.

    docker compose down
    

Примечания

  • Если вы вносите какие-либо изменения в зависимые пакеты, то вам придется выполнить команду docker compose build, как показано выше. Делайте это каждый раз, когда вы добавляете, обновляете или удаляете пакет.
  • Мы предполагаем, что node будет работать на порту 8080. Если для вашего проекта это не так, не стесняйтесь изменить это, но не забудьте изменить это везде, особенно в Dockerfile и docker-compose.yml.
  • Вы можете обнаружить пустой node_modules в каталоге server-code. Это нормально. Когда вы выполняете сборку, каталог node_modules создается внутри вашего образа Docker, но не извлекается с вашей локальной машины. Поэтому пустой node_modules — это нормально.

Производственная сборка и локальное тестирование с контейнерами

Этот рабочий процесс позволяет вам протестировать ваш контейнер, запустив его локально, но с производственными настройками. Это точное соответствие тому, что вы развернули бы на производстве, но это позволяет вам просмотреть вывод консоли, чтобы помочь устранить любые ошибки или недочеты.

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

Шаги для начала работы

  1. Запустите Docker Desktop на локальной машине
  2. Перейдите в основной каталог проекта (не в server-code).
  3. Собрать образ:

    docker build . --target=production -t mynodeapp:1.00
    

    --target=production — это очень важный флаг. Он указывает процессу сборки удалить все зависимости от разработки и посторонние файлы.

    Заметка об имени вашего образа. Я выбрал mynodeapp в качестве имени и версию 1.00. Я предлагаю вам назвать ваше приложение как-нибудь значимо для вас и следовать семантической версионности.

  4. Чтобы запустить экземпляр вашего производственного образа локально, выполните следующую команду:

    docker run -ti --rm -p 8080:8080 mynodeapp:1.00
    

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

Развертывание производственной версии

Развертывание производственного образа выходит за рамки этой статьи. Тем более что это зависит от среды хостинга Docker.

Заключение

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

Вот ссылка на часть 2: https://dev.to/edgarroman/opinionated-docker-development-workflow-for-nodejs-projects-part-2-21ao.

Обратите внимание, что вы, вероятно, захотите прочитать часть 2, когда решите, что хотите внести изменения в рабочий процесс, показанный здесь.

Оцените статью
devanswers.ru
Добавить комментарий