Utiliser NPM/Gulp sous Docker


Toujours dans mon optique de remonter mon environnement de développement sous Windows (au lieu d’Ubuntu, et ce à l’aide de Docker), je me suis aujourd’hui attaqué à un épineux problème : celui de faire fonctionner NPM afin d’utiliser correctement VueJS, Gulp, Webpack, FontAwesome, etc…

La théorie

Sur le papier, tout avait l’air simple : NodeJS fournit une image de base et il n’y a plus qu’à ajouter l’habituel fichier package.json et lancer le tout.

Mais en fait non, car en fait l’image officiel part du principe que vous avez déjà fait tourner votre npm install et que vous êtes donc prêt à balancer votre serveur, avec toutes les dépendances déjà récupérées, etc etc… Or moi ce qui m’intéresse, c’est d’avoir justement un simple fichier package.json et que Docker se charge de récupérer et installer toutes les dépendances pour moi !

Comme indiqué sur certains sites, j’ajoute donc un fichier package.json tout ce qu’il y a de plus basique :

{
  "name": "custom-symfony-project",
  "version": "1.0.0",
  "author": "Pete Gore <pierre@petegore.fr>",
  "description": "Node.JS Docker container for Symfony app",
  "dependencies": {
    "gulp": "^4.0.0"
  },
  "devDependencies": {
    "font-awesome": "*",
    "gulp": "^4.0.0"
  }
}

Et je modifie mon fichier Dockerfile de manière à ce qu’il effectue lui-même le NPM install :

# docker/node/Dockerfile
# See https://github.com/nodejs/docker-node#dockerfile
FROM node:6

EXPOSE 8080

USER node

# set the working directory
RUN mkdir /home/node/app
WORKDIR /home/node/app

# delete existing modules and re-install dependencies
COPY package.json /home/node/app/package.json
COPY package.lock /home/node/app/package.lock
RUN rm -rf node_modules
RUN npm install

# launch the app
CMD  ["npm", "start"]

Enfin, je demande à mon fichier docker-compose.yml d’ajouter ce conteneur :

services:    
    node:
        build: docker/node
        environment:
          - NODE_ENV=dev
        container_name: symfony4-windock-node

Je lance mon docker-compose build qui se passe bien, et ensuite je balance le docker-compose start

 

Et là, c’est le drame.

npm ERR! missing script: start

 

Pas besoin de start

En fait, le souci est « normal » : je balance la commande suivante à la fin de mon DockerFile :

CMD  ["npm", "start"]

Naturellement, dès qu’on appelle une commande du type « start » ou « prestart », ou « run », Node va chercher le script correspondant. Celui-ci se doit d’exister et doit être indiqué dans le fichier package.json.

Dans notre cas, nul besoin de lancer un start car on ne démarre pas un serveur NodeJS, mais on veut juste accéder aux utilitaires en ligne de commande. Je supprime donc cette ligne CMD gênante…

Et là, c’est le drame (encore).

 

Fainéant de conteneur

Lors du start, le conteneur démarre correctement, mais… se coupe aussitôt. Un docker-compose ps indique d’ailleurs bien que l’était n’est pas « Up » mais bien « Exit 0 » , autrement dit sans erreur..!

En fait, comme le conteneur n’a aucun processus qui tourne en arrière plan, il s’arrête gentiment. Mais nous, on veut qu’il reste actif de façon à ce qu’on puisse y entrer en ligne de commande pour faire tourner du gulp et autres utilitaires.

Du coup la solution est toute trouvée : il suffit d’ajouter l’option tty: true à notre ligne de service Node dans le fichier docker-compose.yml :

node:
    build: docker/node
    environment:
      - NODE_ENV=dev
    container_name: symfony4-windock-node
    tty: true

Et voilà notre conteneur Node.JS prêt à fonctionner…!

Enfin presque, il faut maintenant améliorer un peu l’ergonomie de tout ça 🙂