nodejs node how debug node.js gruntjs docker gulp dockerfile

node.js - node - Ejecutar Grunt/Gulp dentro de contenedor Docker o fuera?



nodejs inspect (3)

Estoy tratando de identificar una buena práctica para el proceso de compilación de una aplicación nodejs usando grunt / gulp para ser implementada dentro de un contenedor docker.

Estoy muy contento con la siguiente secuencia:

  • construir usando un gruñido (o trago) fuera del recipiente
  • agregar la carpeta ./dist al contenedor
  • ejecutar npm install (con - marca de producción) dentro del contenedor

Pero en cada ejemplo que encuentro, veo un enfoque diferente:

  • agregar la carpeta ./src al contenedor
  • ejecutar npm install (con dependencias de desarrollo) dentro del contenedor
  • ejecutar la instalación de la planta (si es necesario) dentro del contenedor
  • ejecutar gruñido (o trago) dentro del contenedor

En mi opinión, el primer enfoque genera un contenedor más liviano y eficiente, pero todos los ejemplos que hay por ahí utilizan el segundo enfoque. ¿Me estoy perdiendo de algo?


La única diferencia que veo es que puede reproducir una instalación de gruñido completo en el segundo enfoque.

Con la primera, usted depende de una acción local que podría realizarse de manera diferente, en diferentes entornos.

Un contenedor debe basarse en una imagen que pueda reproducirse fácilmente en lugar de depender de una carpeta de host que contenga "lo que se necesita" (sin saber cómo se ha hecho esa parte)

Si la sobrecarga del entorno de compilación que viene con la instalación es demasiado para una imagen ronca, puede:

  • cree una imagen " app.tar " dedicada a la instalación ( lo hice para Apache, que tuve que volver a compilar , creando un paquete deb en un volumen compartido ).
    En su caso, puede crear un archivo (''tar'') de la aplicación instalada.
  • creando un contenedor desde una imagen base, usando el volumen de ese primer contenedor

    docker run --it --name=app.inst --volumes-from=app.tar ubuntu untar /shared/path/app.tar docker commit app.inst app

Luego, el resultado final es una imagen con la aplicación presente en su sistema de archivos.

Esta es una mezcla entre su enfoque 1 y 2.


Me gustaría sugerir un tercer enfoque que he hecho para un sitio generado estático, la imagen de compilación separada.

En este enfoque, su Dockerfile principal (el que está en la raíz del proyecto) se convierte en una imagen de compilación y desarrollo, básicamente haciendo todo en el segundo enfoque. Sin embargo, reemplaza el CMD en tiempo de ejecución, que consiste en dist.tar carpeta dist construida en un dist.tar o similar.

Luego, tienes otra carpeta (algo así como image ) que tiene un Dockerfile . El rol de esta imagen es solo servir los contenidos dist.tar . Entonces hacemos una docker cp <container_id_from_tar_run> /dist . Luego, Dockerfile solo instala nuestro servidor web y tiene un ADD dist.tar /var/www .

El resumen es algo como:

  • Cree la imagen de Docker del builder (que le proporciona un entorno de trabajo sin servidor web). En este punto, la aplicación está construida. Podríamos ejecutar el contenedor en desarrollo con grunt serve o cualquiera que sea el comando para iniciar nuestro servidor de desarrollo integrado.
  • En lugar de ejecutar el servidor, anulamos el comando predeterminado para cargar nuestra carpeta dist. Algo como tar -cf /dist.tar /myapp/dist .
  • Ahora tenemos un contenedor temporal con un artefacto /dist.tar . Cópielo a su carpeta de Docker de implementación real a la que llamamos image usando docker cp <container_id_from_tar_run> /dist.tar ./image/ .
  • Ahora, podemos construir la pequeña imagen de Docker sin todas nuestras dependencias de desarrollo con la docker build ./image .

Me gusta este enfoque porque todavía es todo Docker. Todos los comandos en este enfoque son comandos de Docker y realmente puede reducir la imagen real que termina desplegando.

Si desea ver una imagen con este enfoque en acción, visite https://github.com/gliderlabs/docker-alpine que usa una imagen de constructor (en la carpeta del constructor) para crear archivos tar.gz que luego se copien a su respectiva carpeta Dockerfile .


Una variación de la solución 1 es tener un "padre -> hijo" que hace que la construcción del proyecto sea realmente rápida. Tendría archivo docker como:

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

Esto manejará la instalación de las dependencias de los nodos y tendrá otro archivo docker que manejará la "instalación" de la aplicación como:

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

con esto, puede continuar su desarrollo y la "construcción" de la imagen de la ventana acoplable será más rápida de lo que sería si tuviera que "reinstalar" las dependencias del nodo. Si instala nuevas dependencias en el nodo, simplemente vuelva a compilar la imagen de dependencias.

Espero que esto ayude a alguien.

Saludos