Как построить образ докера из проекта nodejs в monorepo с рабочими пространствами пряжи - PullRequest
0 голосов
/ 07 мая 2018

В настоящее время мы ищем CI / CD с нашей командой для нашего сайта. Недавно мы также адаптировались к структуре monorepo, поскольку это значительно упрощает наши зависимости и обзор. В настоящее время тестирование и т. Д. Готово для CI, но сейчас я приступаю к развертыванию. Я хотел бы создать образы докеров необходимых пакетов.

Вещи, которые я рассмотрел:

1) Извлеките весь монорепо в проект докера, но запуск установки пряжи в нашем проекте приводит к общему размеру проекта около 700 МБ, и это в основном из-за нашего собственного встроенного приложения, у которого даже не должно быть образа докера. Кроме того, это должно приводить к увеличению времени извлечения образа каждый раз, когда нам приходится развертывать новую версию

2) Связать мои проекты каким-то образом. С нашим интерфейсом у нас есть рабочие настройки, так что все должно быть в порядке. Но я просто попытался добавить веб-пакет в наш Экспресс API и в результате возникла ошибка в моем комплекте из-за этой проблемы: https://github.com/mapbox/node-pre-gyp/issues/308

3) Я попытался запустить установку пряжи только внутри необходимого проекта, но это все равно установит мои node_modules для всех моих проектов.

4) Запустите пакет npm: pkg . В результате получается один файл, готовый для запуска в определенной системе с определенной версией узла. Это работает, но я не уверен, насколько хорошо это будет обрабатывать ошибки и сбои.

5) Другим решением может быть копирование проекта из рабочей области и запуск установки инсталляции пряжи там. Проблема в том, что использование рабочих областей пряжи (неявно связанных зависимостей) так же хорошо, как и раньше. Я должен был бы добавить мои другие зависимости рабочего пространства явно. Возможность ссылается на них из определенного хеша коммита, который я собираюсь проверить прямо сейчас. (РЕДАКТИРОВАТЬ: вы не можете ссылаться на подкаталог как пакет пряжи, кажется)

6) ???

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

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

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

Сначала мы попробовали @ zeit / ncc , были некоторые проблемы, но в итоге нам удалось получить финальные сборки. Он создает один большой файл, который включает весь ваш код, а также весь ваш код зависимостей. Выглядело великолепно. Мне пришлось скопировать в докер образ только нескольких файлов (js, исходные карты, статические ресурсы). Изображения были намного меньше, и приложение работало. НО потребление оперативной памяти сильно выросло. Вместо ~ 70 МБ работающий контейнер потреблял ~ 250 МБ. Не уверен, что мы сделали что-то не так, но я не нашел никакого решения, и есть только одна проблема 1006 *, упоминающая это Я предполагаю, что Node.js загружает анализирует и загружает весь код из пакета, даже если большая его часть никогда не используется.

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

Мы сейчас используем fleggal / monopack . Он связывает наш код с Webpack и передает его Babel. Таким образом, он создает также один пакет файлов, но он не содержит всех зависимостей, только наш код. Этот шаг нам не нужен, но мы не против, чтобы он был там. Для нас важная часть - Monopack копирует только дерево производственных зависимостей пакета в dist / bundled node_modules. Это именно то, что нам было нужно. Изображения Docker теперь имеют размер 100–150 МБ вместо 700 МБ.

Есть один более простой способ. Если в вашем node_modules есть только несколько действительно больших модулей npm, вы можете использовать nohoist в своем корне package.json. Таким образом, пряжа сохраняет эти модули в локальном пакете node_modules, и ее не нужно копировать в образы Docker всех других сервисов.

например:.

"nohoist": [
  "**/puppeteer",
  "**/puppeteer/**",
  "**/aws-sdk",
  "**/aws-sdk/**"
]
0 голосов
/ 31 июля 2019

После долгих проб и ошибок я обнаружил, что осторожное использование файла .dockerignore - отличный способ контролировать ваше окончательное изображение. Это прекрасно работает при запуске под monorepo, чтобы исключить «другие» пакеты.

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

например., cp admin.dockerignore .dockerignore

Ниже приведен пример admin.dockerignore. Обратите внимание на * в верхней части этого файла, что означает «игнорировать все». Префикс ! означает «не игнорировать», т.е. сохранять. Комбинация означает игнорировать все, кроме указанных файлов.

*
# Build specific keep
!packages/admin

# Common Keep
!*.json
!yarn.lock
!.yarnrc
!packages/common

**/.circleci
**/.editorconfig
**/.dockerignore
**/.git
**/.DS_Store
**/.vscode
**/node_modules
0 голосов
/ 14 октября 2018

Я работал над проектом, следуя структуре, похожей на вашу, это выглядело так:

project
├── package.json
├── packages
│   ├── package1
│   │   ├── package.json
│   │   └── src
│   ├── package2
│   │   ├── package.json
│   │   └── src
│   └── package3
│       ├── package.json
│       └── src
├── services
│   ├── service1
│   │   ├── Dockerfile
│   │   ├── package.json
│   │   └── src
│   └── service2
│       ├── Dockerfile
│       ├── package.json
│       └── src
└── yarn.lock

Папка services/ содержит один сервис для каждой подпапки. Каждый сервис написан на node.js и имеет свой собственный package.json и Dockerfile. Обычно это веб-сервер или REST API на основе Express.

Папка packages/ содержит все пакеты, которые не являются службами, обычно это внутренние библиотеки.

Услуга может зависеть от одного или нескольких пакетов, но не от другой услуги. Пакет может зависеть от другого пакета, но не от службы.

Основной package.json (тот, что находится в корневой папке проекта) содержит только некоторые devDependencies, такие как eslint, тестовый прогон и т. Д.

Человек Dockerfile выглядит следующим образом, предполагая, что service1 зависит от обоих package1 & package3:

FROM node:8.12.0-alpine AS base

WORKDIR /project

FROM base AS dependencies

# We only copy the dependencies we need
COPY packages/package1 packages/package1
COPY packages/package3 packages/package3

COPY services/services1 services/services1

# The global package.json only contains build dependencies
COPY package.json .

COPY yarn.lock .

RUN yarn install --production --pure-lockfile --non-interactive --cache-folder ./ycache; rm -rf ./ycache

Фактические Dockerfile s, которые я использовал, были более сложными, так как они должны были создавать подпакеты, запускать тесты и т. Д. Но вы должны понять с этим примером.

Как видите, хитрость заключалась в том, чтобы копировать только те пакеты, которые необходимы для конкретной службы. Файл yarn.lock содержит список package @ version с точной версией и разрешенными зависимостями. Чтобы скопировать его без всех подпакетов, это не проблема, yarn будет использовать версию, разрешенную там, при установке зависимостей включенных пакетов.

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

Для краткости, в этом ответе я пропустил много деталей, не стесняйтесь спрашивать о точности в комментарии, если что-то не совсем понятно.

...