Note: déprécié au profit de [Docker][NodeJS] Utiliser Docker pour créer un environnement de développement NodeJS.
Accès rapide aux commandes Docker utiles
Docker for Gulp Build Tasks et version PDF pour la postérité. Cet article m’a permis de mettre en place un Docker pour compiler mes sources Front-End via NPM (workflow utilisant Bower et Gulp). Et ça marche!!!
ATTENTION: ce Docker fonctionne bien (les sources en local sont compilées via le conteneur), à l’exception de Browsersync qui ne recharge pas l’aperçu dans le navigateur.
TODOs
-
Les fichiers compilés (dossier dist/) sont bien modifiés en local, mais on ne voit pas les modifications en front dans le navigateur. Hypothèse: on voit les fichiers présents dans le conteneur (qui eux ne sont pas modifiés) et pas les fichiers locaux.
le truc c’est t’utilise pas du tout de volumes
donc en gros t’es sources sont accessible dans l’image docker, que parce que y’a un copy dans ton Dockerfile
ca arrive qu’une fois lors du build de l’image
donc si tu modifie ton code après coup, ton image docker le verra pas, car le code updaté ne lui est pas fourni
Pourquoi Docker?
Par souci de portabilité de l’environnement de travail.
Problème de versions de nodeJS et de ses dépendances d’un poste de travail à l’autre…
Prérequis
Avoir Docker d’installé, avoir Git d’installé.
Conventions pour ce tutoriel
Nous partirons du principe que nos fichiers de travail se trouvent dans un dossier docker/fzt-master
. Vous pouvez créer le dossier docker/ via la commande mkdir docker
, mais ne créez pas le dossier fzt-master/ pour le moment.
Attention: si vous utilisez un IDE, il est important que les fins de lignes dans vos fichiers soient au format « Unix ». Dans Sublime Text 3 par exemple, menu View > Line endings > Unix.
Mon environnement de travail est un Ubuntu server dans une VM que je lance depuis un Windows 10 via Virtual Box.
Rapatriement des sources de Foundation
A la racine d’un dossier nommé docker/, exécuter la commande suivante pour récupérer les sources de Foundation Zurb Template (branche master) en local via Git dans un dossier fzt-master/: git clone https://github.com/zurb/foundation-zurb-template.git ftz-master
Se placer à la racine du dossier fzt-master (commande cd fzt-master
), créer un fichier Dockerfile (commande touch Dockerfile
) et l’éditer pour y placer les lignes de code suivantes (commande vim Dockerfile
ou vi Dockerfile
si vim n’est pas installé sur votre machine) :
Dans vim, on passe en mode « insertion » en tapant la touche Inser du clavier, ce qui nous permet d’éditer le fichier. La combinaison de touches :wq! nous permet ensuite de sauvegarder les modifications apportées au fichier et de quitter.
Dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
FROM ubuntu:16.04 WORKDIR /home/app/ COPY . /home/app/ ADD setup_8.x /tmp/setup_8.x RUN bash /tmp/setup_8.x RUN apt-get update RUN apt-get install -y build-essential nodejs RUN /usr/bin/npm install -g yarn gulp babel-core babel-preset-env babel-register babel-loader gulp-babel browser-sync #RUN rm -rf node_modules/ RUN npm install RUN yarn CMD ["yarn", "start"] |
docker-compose.yml
De manière à pouvoir exploiter browser-sync et le live reload, il faut également créer un fichier docker-compose.yml qui va s’occuper de rediriger les ports du conteneur vers notre machine locale afin que nous ayons accès au résultat de nos fichiers compilés dans notre navigateur préféré (explication ici) :
|
version: '2' services: fzt-master: image: fzt-master build: context: ./ dockerfile: Dockerfile ports: - 4000:8000 |
Vos sources devraient être accessibles dans votre navigateur depuis l’URL: http://localhost:4000 ou ip.de.votre.vm:4000
Pour récupérer l’IP de votre VM, taper la commande ifconfig
. Choisir celle qui commence par 192.168.
.
gulpfile.babel.js
Il faudra également éditer le fichier gulpfile.babel.js en local pour ajouter le paramètre open: false
à la fonction server
:
|
// Start a server with BrowserSync to preview the site in function server(done) { browser.init({ server: PATHS.dist, port: PORT, open: false }, done); } |
Initialiser le conteneur Docker
Builder le conteneur: docker build -t fzt-master .
edit: la tâche de build sera effectuée par le docker-compose, juste en-dessous.
A la racine du dossier où se trouvent les fichiers Dockerfile et docker-compose.yml, exécuter la commande: docker-compose up -d
Puis (la première fois et à chaque modification du fichier package.json) installer, via le conteneur, les dépendances NPM en local: docker run --rm -v ~/docker/fzt-master:/home/app/ fzt-master npm install
edit: la commande npm install
a été ajoutée d’office dans le Dockerfile.
Image for service fzt-master was built because it did not already exist. To rebuild this image you must use docker-compose build
or docker-compose up --build
.
Exploiter le conteneur Docker
Lancer le conteneur afin qu’il exécute la commande par défaut (yarn start
) : docker run --rm --pid=host -v ~/docker/fzt-master:/home/app/ fzt-master
L’argument --pid=host
sert à stopper la tâche de compilation des sources dans votre conteneur en utilisant le traditionnel raccourci ctrl + c.
ATTENTION: ce billet est expérimental. Il ne garantit en rien que vous puissiez réellement être en mesure de compiler les sources de Foundation dans un conteneur en suivant les directives ci-dessous. Je suis en-train de mettre en place le Dockerfile qui permettra de le faire. Ce billet constitue des notes de travail. En fonction de mon avancement, vous arriverez peut-être à quelque chose. Je retirerai ce message lorsque le Dockerfile sera fonctionnel comme je l’entends.
Pour aller plus loin:
uwegerdes/frontend-development
Browsersync within a Docker container
How to run livereload with gulp within a docker container?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
FROM ubuntu:16.04 WORKDIR /home/app/ COPY . /home/app/ #ADD setup_0.12 /tmp/setup_0.12 #RUN bash /tmp/setup_0.12 ADD setup_4.x /tmp/setup_4.x RUN bash /tmp/setup_4.x #ADD setup_11.x /tmp/setup_11.x #RUN bash /tmp/setup_11.x RUN apt-get update && apt-get install -y build-essential nodejs git RUN /usr/bin/npm install -g npm@4 bower babel-core babel-loader babel-preset-es2015 babel-register browser-sync gulp gulp-babel gulp-cli RUN /usr/bin/npm install RUN /usr/bin/bower install CMD ["npm", "start"] |
Le Dockerfile décortiqué
Pour paramétrer correctement le Dockerfile, il convient d’aller chercher quelques informations dans les fichiers readme.md et package.json du repo Git de Foundation que nous venons de cloner. Attention à bien chercher ces informations dans la branche que nous venons de cloner (v6.4). Le framework évolue sans arrêt et les informations, les paquets NPM (et leurs versions) et les commandes dont nous avons besoin pour, respectivement, constituer le Dockerfile et compiler notre code source sans erreurs sont différents d’une branche à l’autre du projet.
Embarquer la bonne version de nodeJS
Premièrement, vérifier la version de nodeJS à installer pour faire fonctionner correctement les dépendances utilisées lors de la compilation des sources. La section Installation du fichier readme.md nous renseigne sur ce point:
NodeJS (0.12 or greater)
Nous pourrons trouver ce fichier qui constitue le script d’installation de la version 0.12 de nodeJS sur le repository Git officiel du projet node. Il est à récupérer et à copier/coller dans le dossier fzt64, à la racine (au même niveau que le Dockerfile).
Pour d’autres versions du framework Foundation ou d’autres projets dont la compilation des sources reposent sur NPM, la liste des scripts d’installation de l’ensemble des distributions de nodeJS se trouve ici.
|
ADD setup_0.12 /tmp/setup_0.12 RUN bash /tmp/setup_0.12 |
Edit: pour des raisons que j’ignore (quoique, peut-être un problème relatif à la version 16.04 d’ubuntu server que je déclare et qui serait trop récente… je n’ai pas testé avec une petite 14.04 mais je devrais…), le build du container semble ne pas fonctionner avec la version 0.12 de nodeJS préconisée dans la branche v6.4 de Foundation. Peut-être une erreur de mise à jour dans leur readme…
Step 9/13 : RUN /usr/bin/npm install -g babel-core
—> Running in 510dcfa93753
/bin/sh: 1: /usr/bin/npm: not found
The command ‘/bin/sh -c /usr/bin/npm install -g babel-core’ returned a non-zero code: 127
Je la remplace donc par la version 4.x qui lui succède chronologiquement.
|
ADD setup_4.x /tmp/setup_4.x RUN bash /tmp/setup_4.x |
Je pourrais tenter de la remplacer par la version en cours (11.x au moment où j’écris ces lignes…), mais je m’expose à des incompatibilités avec les versions de certains paquets NPM utilisés dans la branche v6.4 de la stack Zurb (trop grand gap de versions entre nodeJS et les paquets). C’est notamment ce problème que nous essayons d’éviter en mettant à profit Docker.
Troubleshooting et installation des applications et devDependencies manquantes
On ne peut pas toujours deviner quelles applications et devDependencies doivent être obligatoirement installées dans le conteneur. Il y a bien un fichier package.json dans le projet, mais toutes les devDependencies ne doivent pas obligatoirement être installées via le Dockerfile. Il faut y aller à tâtons et fixer une à une les erreurs retournées par le terminal lors du build du conteneur.
https://github.com/zurb/foundation-zurb-template/blob/v6.4/package.json#L16
$ docker run –rm -v ~/docker/fzt64:/home/app/ fzt64
> foundation-zurb-template@1.0.0 start /home/app
> gulp
[14:26:11] Failed to load external module @babel/register
[14:26:11] Failed to load external module babel-register
[14:26:11] Failed to load external module babel-core/register
[14:26:11] Failed to load external module babel/register
[14:26:11] Local gulp not found in /home/app
[14:26:11] Try running: npm install gulp
|
RUN /usr/bin/npm install -g bower babel-core babel-register gulp |
Step 9/11 : RUN /usr/bin/npm install
—> Running in 95a31683f7c9
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: undefined
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: undefined
npm WARN deprecated gulp-uncss@1.0.6: Use UnCSS through gulp-postcss instead.
npm WARN deprecated babel-preset-es2015@6.24.1: ???? Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
npm ERR! Linux 4.4.0-57-generic
npm ERR! argv « /usr/bin/node » « /usr/bin/npm » « install »
npm ERR! node v4.9.1
npm ERR! npm v2.15.11
npm ERR! code ENOGIT
npm ERR! not found: git
npm ERR!
npm ERR! Failed using git.
npm ERR! This is most likely not a problem with npm itself.
npm ERR! Please check if you have git installed and in your PATH.
npm ERR! Please include the following file with any support request:
npm ERR! /home/app/npm-debug.log
The command ‘/bin/sh -c /usr/bin/npm install’ returned a non-zero code: 1
npm ERR! not found: git. Il faut ajouter Git à la liste des paquets à installer.
|
RUN apt-get update && apt-get install -y build-essential nodejs git |
Step 8/10 : RUN /usr/bin/npm install
—> Running in f25efff29bd2
npm WARN deprecated gulp-uncss@1.0.6: Use UnCSS through gulp-postcss instead.
npm WARN deprecated babel-preset-es2015@6.24.1: ???? Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
npm ERR! git rev-list -n1 4.0: fatal: ambiguous argument ‘4.0’: unknown revision or path not in the working tree.
npm ERR! git rev-list -n1 4.0: Use ‘–‘ to separate paths from revisions, like this:
npm ERR! git rev-list -n1 4.0: ‘git […] — […]’
npm ERR! git rev-list -n1 4.0:
npm ERR! git rev-list -n1 4.0: fatal: ambiguous argument ‘4.0’: unknown revision or path not in the working tree.
npm ERR! git rev-list -n1 4.0: Use ‘–‘ to separate paths from revisions, like this:
npm ERR! git rev-list -n1 4.0: ‘git […] — […]’
npm ERR! git rev-list -n1 4.0:
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: Cloning into bare repository ‘/root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa’…
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: Host key verification failed.
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: fatal: Could not read from remote repository.
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa:
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: Please make sure you have the correct access rights
npm ERR! git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa: and the repository exists.
npm ERR! Linux 4.4.0-57-generic
npm ERR! argv « /usr/bin/node » « /usr/bin/npm » « install »
npm ERR! node v4.9.1
npm ERR! npm v2.15.11
npm ERR! code 128
npm ERR! Command failed: git clone –template=/root/.npm/_git-remotes/_templates –mirror git@github.com:gulpjs/gulp.git /root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa
npm ERR! Cloning into bare repository ‘/root/.npm/_git-remotes/git-github-com-gulpjs-gulp-git-ed33b0aa’…
npm ERR! Host key verification failed.
npm ERR! fatal: Could not read from remote repository.
npm ERR!
npm ERR! Please make sure you have the correct access rights
npm ERR! and the repository exists.
npm ERR!
npm ERR!
npm ERR! If you need help, you may report this error at:
npm ERR!
npm ERR! Please include the following file with any support request:
npm ERR! /home/app/npm-debug.log
The command ‘/bin/sh -c /usr/bin/npm install’ returned a non-zero code: 1
Il faut ajouter gulp-cli à la liste des dépendances NPM à installer. Voir ici et là.
|
RUN /usr/bin/npm install -g bower babel-core babel-loader babel-preset-es2015 babel-register browser-sync gulp gulp-babel gulp-cli |
Builder le container
Pour builder le container (que je vais appeler « fzt64 »), j’exécute la commande: docker build -t fzt64 .
Installer les paquets node en local, via le container
Then open the folder in your command line, and install the needed dependencies:
cd projectname
npm install
bower install
Commande à exécuter obligatoirement avant toute autre pour récupérer les dépendances NPM du projet (dossier node_modules) en local.
Pour exécuter la commande npm install
à l’intérieur de mon container (et ainsi récupérer les dépendances node propres au projet Foundation en local sur ma machine, à la racine du dossier home/intlangf/docker/fzt64/ où se trouve le fichier package.json), j’exécute la commande docker run --rm -v ~/docker/fzt64:/home/app/ fzt64 npm install
Pareil pour Bower: docker run --rm -v ~/docker/fzt64:/home/app/ fzt64 bower install
Commande par défaut
La section Manual setup du fichier readme.md nous renseigne sur les différentes commandes fournies par la stack Zurb:
Finally, run npm start to run Gulp. Your finished site will be created in a folder called dist, viewable at this URL:
http://localhost:8000
To create compressed, production-ready assets, run npm run build.
La commande npm start
est la commande par défaut dans notre Dockerfile.
Ceci signifie que lorsqu’on exécute la commande docker run --rm -v ~/docker/fzt64:/home/app/ fzt64
dans notre terminal, c’est en réalité la commande npm start
qui sera exécutée dans notre container. Elle génèrera un dossier dist/ en local (à la racine du dossier docker/fzt64/) qui contiendra le résultat de la compilation des différentes sources de Foundation.
Exécuter une commande autre que celle par défaut
On voit que d’autres commandes sont disponibles au sein de la stack Zurb.
docker run --rm -v ~/docker/fzt64:/home/app/ fzt64 npm run build
Commandes utiles
Lister les images disponibles: docker images -a
.
Supprimer des images en utilisant leurs IDs ou leurs tags: docker rmi <Image> <Image>
.