Search
Write a publication
Pull to refresh

Comments 36

Современным способом запуска node-пиложений является
CMD [ «node», «index.js» ]
Ну кстати да, контейнеры так-то удобнее будут. Упало приложение — упал контейнер.

С контейнерами все отлично если это под kubernetes — в остальных случаях скорее больше чем меньше проблем.

А почему контейнер должен упасть, если упало приложение? Я с контейнерами знаком слабо, но по моим представлениям так быть не должно (по крайней мере в docker'е).

Докер (или надстройки над ним) заботятся о замене контейнера, если основной процесс в нём упал. Процесс в контейнере не демонизируется даже.

Именно так и должно быть. контейнер обязан падать при падении приложения.

Заинтригован. Не могли бы вы дать ссылку на описание этого способа запуска?

CMD это имеется в виду ситнаксис Dockerfile например можно почитать в не моей статье https://habr.com/ru/company/southbridge/blog/329138/


Если основной процесс валится то и контейнер валится. Можно этого избежать если основной просеыы будет например supervisor но это будет уже не docker way


Кстати supervisor это еще один способ запустить то что нужно.


Проблема докер-контейнеров в том что для реальной работы на проде они требуют оркестратор в качестве которого выступает например nomad или cubernetes — которые как раз и следят чтобы процесс был рабочий и в случае ошибки запускают новый процесс. Но по сравнению с pm2 для оркестратура нужно еще очень и очень много чего.

restart always или on failure базовая фича докера. Для перезапуска дополнительно оркестраторы не нужны. Они для реплицирования и обнаружения (связи) сервисов прежде всего

Речь скорее о том что запускать контейнеры на проде командной строкой в 100500 символов не так уж удобно. А от этой командной строки как раз зависит что и как собственно будет работать


Например если я хочу разобраться как работает хостовый не в докере nginx или mysql я изучаю его конфиги. В случае докере мне для этого нужно ещё знать командную строку, dockerfile которого может и не быть в исходниках а где-то взят готовый чужой имидж.

Какие-то надуманные проблемы. Чтобы запускать сервер — надо будет знать 100500 символов настройки этого сервера (установка всего и вся, настройка портов, копирование конфигов). А переехать на другой сервер — это значит опять всё устанавливать и не факт, что что-нибудь не забудется и/или версия пакета не обновится. А с докером: установить докер, скачать проект и запустить подготовленную строку.


Чужой имидж — это просто стандартный официальный имидж от разработчика приложения, который легко настраивается и всегда предсказуемо вебя ведёт. Не представляю, чтобы кто-то использовал какой-то мутный имидж от no-name. Проще самому написать.

Откуда берутся мутные имиджи. Девопс творческий в кавычках и без кавычек человек. Слабо контролиуемый так как в его хозяйство никто не лезет. Фигачит налево и направо кастомные имиджи и заливает их на публичные хабы. Прошли годы. Сломался проект или нужно как Вы справедливо заметели переместить проект на другой сервер. И тут начинаются не надуманные проблемы.

Если в примере имидж — "мутный", то в примере без docker'a — у вас не будет никаких сведений (или очень поверхностных) о конфигурации сервера. Но это крайние случаи — и оба варианта одинаково неприятны. Тут причина не в docker'e, а в девопсе.
В моём опыте не крупных проектов с dockerfile'ами (без выделенного девопса) — они хранятся либо в самом проекте в папке docker, либо в отдельном репозитории той же компании. Это значительно упрощает настройку как локального окружения, так и сервера.

Спасибо что обратили внимание на такую проблему. Я бы все же работал скорее с pm2 например как описано в статье https://en.programqa.com/question/52499715/ т.к. pm2 это (если не под cubernetes) наверное наилучший вариант.

Спасибо за ссылку. Интересный workaround. Попробовал его применить на тестовом сервисе. Добавил в package.json:


  "scripts": {
    "safestart":"node --experimental-modules src/app_es6.mjs"
  }

и запустил сервис командой:


$ pm2 start npm  -- run safestart

Видно, что ES6-приложение запускается:


$ pm2 log
...
/home/alex/.pm2/logs/npm-error.log last 15 lines:
0|npm      | (node:11489) ExperimentalWarning: The ESM module loader is experimental.

/home/alex/.pm2/logs/npm-out.log last 15 lines:
0|npm      | 
0|npm      | > pm2es6@0.1.0 safestart /home/alex/work/sof_es6_pm
0|npm      | > node --experimental-modules src/app_es6.mjs
0|npm      | 
0|npm      | ES6 app listening on port 3000!
0|npm      | Hello World! ES6 module is here.

0|npm  | Hello World! ES6 module is here.
0|npm  | Hello World! ES6 module is here.
0|npm  | Hello World! ES6 module is here.

К сожалению, нельзя использовать возможности кластеризации (-i 4) — запускается только первый инстанс приложения, остальные сваливаются. Но и то, что есть, гораздо интереснее выглядит, чем forever или systemd.

Попробовал так (npm run cluster):


{
  "type": "module",
  "scripts": {
    "start": "node --experimental-modules app.js",
    "cluster": "pm2 -i 4 start npm -- run start"
  },
}

Вроде запустилось:
image

Попробовал так же. Похоже, что запускается только один процесс, хотя pm2 думает, что запустились все:


в pm2-логах также видны ошибки:


$ pm2 log
...
1|npm      | npm ERR! code ELIFECYCLE
1|npm      | npm ERR! errno 1
1|npm      | npm ERR! pm2es6@0.1.0 safestart: `node --experimental-modules src/app_es6.mjs`
1|npm      | npm ERR! Exit status 1
1|npm      | npm ERR! 
1|npm      | npm ERR! Failed at the pm2es6@0.1.0 safestart script.
1|npm      | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

В "нормальном" кластере запускается указанное кол-во процессов:


alex@omen17:~/work/sof_es6_pm$ ps -Af | grep app_
alex     10903 25382  2 08:29 ?        00:00:00 node /home/alex/work/sof_es6_pm/src/app_cjs.js
alex     10910 25382  3 08:29 ?        00:00:00 node /home/alex/work/sof_es6_pm/src/app_cjs.js
alex     10919 25382  2 08:29 ?        00:00:00 node /home/alex/work/sof_es6_pm/src/app_cjs.js
alex     10932 25382  3 08:29 ?        00:00:00 node /home/alex/work/sof_es6_pm/src/app_cjs.js

Думаю, что в моём тестовом приложении идёт конкуренция за порт 3000 для express-сервера. Какой-то из процессов первым захватывает порт, остальные отваливаются по ошибке. В логах это видно — при 4 экземплярах в кластере сообщений об ошибке только 3. pm2 каким-то образом обрабатывает вариант с портом самостоятельно, но как только мы стартуем приложение через node/npm, то pm2 теряет эту возможность.

Попробовал еще с модулем esm и конфигом `ecosystem.config.js` для PM2:


module.exports = {
  apps: [
    {
      name: 'PM2 Demo App',
      script: './app.js',
      instances: 4,
      exec_mode: 'cluster',
      node_args: '-r esm'
    }
  ]
}

Логи без ошибок.

А почему запускали на 12ой ведь они там под флагом? Почему не попробовали тоже самое для 13.2.0+ без флага?

12-я версия — LTS (Long Term Support). Только поэтому.

Long Term Support — это про стабильность. А модули пока ещё экспериментальные и их стабильность не гарантируется. Поэтому, в вашем случае от LTS пользы нет

LTS — это наиболее вероятная версия софта. Я рассматривал частый кейс, а не последний. У меня и Ubuntu стоит 18.4 по той же причине — стабильность.

Если хочется использовать es6 модули, то почему бы не воспользоваться бабалем?

Бабелем я пользовался когда еs6 был еще практически без поддержки на нативном уровне. Сейчас когда все практически нативно бабелем нет резона пользоваться. Я даже в свое время отказался для этого от import в пользу require
Сейчас я скорее предпочел бы не использовать import, чем использовать бабел.

Ещё бы рекомендовал использовать ecosystem.config.js в pm2. Про environments не забыть тоже с примерами.
Давно пользуюсь pm2. Но вот тоже думаю пора в Докер. Ибо развёртывание приложений на новые машины уже утомляет, но я и не DevOps, просто FullStackJS. Пока не было задач, где бы я мог на 100% оправдать использование Докера. Чтобы выделить время на полное изучение его workflow.А очень хочется.

От девопосов всё чаще слышу, что от разработчиков они ожидают минимум докерфайл (манифест для сборки контейнера) для включения нового сервиса или ui в систему. Типа сеньору уже не простительно не знать Докер хотя бы поверхностно, они потом оптимизируют, дотюнят, но базу им надо.


А если вы занимаетесь разворачиванием на продакшен, то вы уже девопс в современных массовых понятиях.

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

Можно рассматривать базовый докерфайл и ко от разрабов как доку для девопса. Какие енв переменные приложение ожидает, какие конфиги, как его вообще собирать из исходников и как запускать. Есть и другие способы, конечно. И часть из них тоже отчасти самодокументируемые типа набора баш-скриптов, но плюс докера и подобных подходов (вагрант, например) — разработчик вынужден полностью описывать среду для своего приложения. Нет места (почти) "ой, забыл сказать, что нужно новое расширение для языка установить, я-то его ещё в первый день работы установил себе, наверное, но в проекте раньше не использовалось"

Докер это очень просто, например гораздо проще чем bash. Нужно просто понять зачем он нужен. Но вот докер на проде это уже сложно. Т.к. без средств оркестрации на проде докер предоставит больше проблем чем преимуществ. А вот средства оркестрации это уже сложнее. Например cubernetes практически невозможно развернуть и главное поддерживать в рабочем состоянии не специалисту. Поэтому приходится покупать облачный. Поэтому его пиарят нещадно. Nomad реально развернуть и поддерживать самостоятельно но мало специалистов.

Докер не проще чем баш, потому что без баша нормально с докером работать не получится обычно :)

Возможно я отстал от жизни или прилетел с другой планеты — но неужели JS настолько популярнее стандартных С/С++/С#, что он активно развивается на стороне сервера?

С на стороне сервера используется для написание собственно серверов. Веб приложения как правило на с не пишут. Js используется чаще чем с. С# это как бы в основном для экосистемы windows. Для этой экосистемы с# скорее всего превалирует.

Менеджер процессов, подобный pm2, является очень полезным сервисом в мире серверного JS. Но, к сожалению, сам pm2 не позволяет запускать современные nodejs-приложения (в частности — с ES6-модулями).

Я сильно не изучал этот момент, но у меня вполне получается через pm2 запускать package.json-скрипт с передачей этого флага, и все работает норм.
«scripts»: {
«start-server»: «node --experimental-modules src/server/»,

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

ОК. Буду знать. Хотя мне не доводилось еще сталкиваться с этой проблемой.
Sign up to leave a comment.

Articles