Run Grunt/Gulp внутри контейнера Docker или снаружи?

Я пытаюсь определить хорошую практику для процесса сборки приложения nodejs с использованием grunt/ gulp для развертывания внутри контейнера докеров.

Я очень доволен следующей последовательностью:

  • построить с помощью внешнего grunt (или gulp)
  • добавить. /dist папку в контейнер
  • запустить npm install (с флагом --production) внутри контейнера

Но в каждом примере, который я нахожу, я вижу другой подход:

  • добавить. /src папку в контейнер
  • запустить npm install (с зависимостями dev) внутри контейнера
  • запустить bower install (если требуется) внутри контейнера
  • запустить grunt (или gulp) внутри контейнера

IMO, первый подход создает более легкий и эффективный контейнер, но во всех примерах используется второй подход. Я что-то пропустил?

Ответы

Ответ 1

Единственное различие, которое я вижу, это то, что вы можете воспроизвести полную установку grunt во втором подходе.

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

Контейнер должен быть основан на изображении, которое можно легко воспроизвести, а не в зависимости от папки хоста, которая содержит "что необходимо" (не зная, как эта часть была выполнена).


Если накладные расходы среды сборки, которые поставляются с установкой, слишком велики для изображения ворчания, вы можете:

Тогда конечный результат - это изображение с приложением, присутствующим в его файловой системе.

Это сочетание между вашим подходом 1 и 2.

Ответ 2

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

В этом подходе ваш основной Dockerfile (тот, что в корне проекта) становится образ построения и разработки, в основном делая все во втором подходе. Тем не менее, вы переопределяете CMD во время выполнения, что должно деформировать встроенную папку dist в dist.tar или аналогичную.

Затем у вас есть другая папка (что-то вроде image), у которой есть Dockerfile. Роль этого изображения заключается только в обслуживании содержимого dist.tar. Итак, мы делаем docker cp <container_id_from_tar_run> /dist. Затем Dockerfile просто устанавливает наш веб-сервер и имеет ADD dist.tar /var/www.

Резюме - это что-то вроде:

  • Создайте образ builder Docker (который получает рабочую среду без веб-сервера). В данный момент приложение построено. Мы могли бы запустить контейнер в разработке с помощью grunt serve или что бы команда не запустила наш встроенный сервер разработки.
  • Вместо того, чтобы запускать сервер, мы переопределяем команду по умолчанию, чтобы разгрузить нашу папку dist. Что-то вроде tar -cf /dist.tar /myapp/dist.
  • Теперь у нас есть временный контейнер с артефактом /dist.tar. Скопируйте его в папку фактического развертывания Docker, которую мы назвали image, используя docker cp <container_id_from_tar_run> /dist.tar ./image/.
  • Теперь мы можем создать небольшое изображение Docker без всех зависимостей разработки с docker build ./image.

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

Если вы хотите проверить изображение с этим подходом в действии, посмотрите https://github.com/gliderlabs/docker-alpine, который использует образ строителя (в построителе ) для создания файлов tar.gz, которые затем копируются в их соответствующую папку Dockerfile.

Ответ 3

Вариант решения 1 состоит в том, чтобы иметь "родительский → ребенок", который делает сборку проекта очень быстрым. У меня был бы файл dockerfile:

FROM node
RUN mkdir app
COPY dist/package.json app/package.json
WORKDIR app
RUN npm install

Это обработает установку зависимостей node и добавит другой файл докеров, который будет обрабатывать приложение "установка", например:

FROM image-with-dependencies:v1
ENV NODE_ENV=prod
EXPOSE 9001
COPY dist .
ENTRYPOINT ["npm", "start"]

с этим вы можете продолжить свою разработку, а "сборка" изображения докеров будет быстрее того, что было бы, если вам нужно "переустановить" зависимости node. Если вы установите новые зависимости на node, просто заново создайте образ зависимостей.

Надеюсь, это поможет кому-то.

Привет