RSS Feed

Archives de la catégorie ‘Linux’

Docker – en route pour la SOA et les micro-services !

25 November 2014 par SeB Pas de commentaire »

Comme certains l’on déjà pu annoncer, la révolution Docker est en ordre de marche. Je n’ai pas encore pris le temps de bien expliquer ce qu’était Docker. En revanche, voici quelques avantages et surtout les impacts que cet outil peut avoir sur l’architecture de vos solutions.

VMs légères ?

Docker n’est pas une solution de VMs mais de containers. Cependant, la comparaison est facile et tout le monde est tenté de la faire. Dans un souci de vulgarisation, on peut donc s’autoriser à dire que Docker permet de créer des VMs très légères :

  • en terme d’espace disque : l’image du container n’embarque pas tout l’OS et le découpage en couche des images permet de réduire d’espace occupé pour leur stockage
  • pour la rapidité de démarrage : un container démarre en quelques secondes (c’est l’applicatif qui prend le plus de temps à démarrer)
  • avec une performance accrue : il n’y a plus d’émulation d’OS, l’overhead est donc réduit et les performances disque et réseaux semblent au rendez-vous

Un déploiement universel ?

L’avantage principal des containers réside dans leur promesse : développez une fois, déployez n’importe où !
Effectivement, jusqu’à présent, nous devions packager nos applications à partir des sources et fournir un ensemble de fichiers de configuration et de scripts de déploiement pour des livraisons sur les environnements autre que le développement. Avec Docker, tout celà est terminé. Vous définissez une fois pour toute l’éco-système de votre application (OS, applications et configuration) pour générer une image auto-suffisante. Vous l’enregistrez sur un dépôt partagé. Ensuite, n’importe quel système ayant Docker d’installé et un accès au dépôt peut déployer l’application sans avoir à lancer l’installation ou la configuration de quoi que ce soit. Adieu les erreurs de déploiement !

On peut rapidement imaginer le workflow à mettre en place pour faire au minima du continuous delivery mais surtout du continuous deployment !

Une nouvelle architecture ?

Pas si sûr…

Les containers Docker ne permettent pas de persister un état. Il faut passer par des services externes (d’autres containers ou des volumes) très faciles à mettre en place avec le système de liens inter-containers.
Si l’on ajoute les contextes d’exécution légers (pour ne pas parler de VMs :-P) et le déploiement aisé, il en résulte qu’un container doit contenir une portion de code très petite et doit être concentré sur un rôle (du métier) bien particulier. Or quelle architecture propose de décomposer un service métier de haut niveau (l’application) en un assemblage de composants indépendants et organisés par silo (les containers) ? Oui, oui. On parle bien de SOA ici.

Par ailleurs, le système de mise à jour des images Docker, permet de mettre à jour sans risque un composant qui tourne dans un container indépendant sans impacter le reste du système.

Enfin, la capacité de Docker à isoler les composants, à les déployer n’importe où et à favoriser le packaging de composants réutilisables (via des containers multi-tenants) avec un périmètre très limité, tend à aller au délà de la SOA en implémentant des micro-services !

Ces ressentiments m’ont été confirmés à la lecture de Docker: VMs, code migration and SOA solved. J’espère que cet article vous laisse entrevoir un début des possibilités offertes par Docker.

 

Docker – construction automatique sur Docker Hub

31 October 2014 par SeB Pas de commentaire »

Comme évoqué précédemment, Docker propose un dépôt d’images publiques. Après s’être inscrit sur ce Docker Hub, vous pouvez partager vos images Docker via la commande suivante :

$ sudo docker push votrelogin/votreimage

Cependant, Docker Hub permet également de construire automatiquement vos images à partir de vos sources (depuis GitHub ou Bitbucket). Pour celà, il faut se rendre sur la page de vos dépôts d’images, cliquer sur “Add”, puis choisir “Automated Build”. Ensuite, il faudra choisir votre hébergeur de sources et enfin votre dépot Git contenant vos sources. Seul le fichier Dockerfile est obligatoire. Mais la présence d’un README.md permet d’afficher automatiquement une description de votre image sur le Docker Hub.

Avec cette fonctionnalité de construction automatique, Docker Hub déclenche automatiquement un build de votre image dès que vous faites un commit sur votre dépôt de sources. Votre dépôt d’images Docker se synchronise donc tout seul avec votre dépôt de sources Git.

Une documentation explique plus en détail comment fonctionne la construction automatique d’image Docker.

raml-logo

J’ai testé cette fonctionnalité pour l’image de l’api:Console. Vous pouvez donc tester le déploiement de cette image via les commandes suivante :

$ docker pull slecache/api-console
$ docker run -p 9000:9000 -d slecache/api-console

Pour information, les sources sont disponibles sur GitHub et l’image sur Docker Hub.

A vos remarques et éventuelles contributions ! :-)

PS : Tiens donc ! Après une recherche sur Docker Hub pour trouver la propre image, je ne suis rendu-compte que quelqu’un à eu la même idée que moi aujourd’hui… :-o

 

Docker – premier container pour l’api:Console

30 October 2014 par SeB Pas de commentaire »

raml-logoSi vous me lisez, vous avez pu remarquer lors de mon article sur Vagrant vs Ubuntu vs NPM vs Bower que j’utilise l’api:Console de MuleSoft pour déployer en ligne de la documentation au format RAML pour des APIs REST.

Cette console tourne correctement dans Vagrant mais je ne suis dis que la création un container pour cette application serait une première application de Docker judicieuse et adaptée. :-)

Recherche d’une Base Docker Image

La première étape est de vérifier s’il n’existe pas déjà un container qui le fait déjà dans le Docker Hub Registry. Je n’ai rien trouvé.

Ensuite, avant de construire une image à partir de rien, il est plus rapide de se baser sur une image existante. L’api:Console nécessite l’installation de Node.js, Bower et Grunt. Justement, Docker propose eux-même une image avec ces outils : dockerfile/nodejs-bower-grunt. Nous allons donc la réutiliser.

Construction de l’image Docker

Afin de capitaliser sur la construction de cette image, nous allons utiliser un Dockerfile :

FROM dockerfile/nodejs-bower-grunt
MAINTAINER John DOE "xxxxxxxx@gmail.com"

# télécharge la dernière version de l'api:Console pour RAML
RUN git clone https://github.com/mulesoft/api-console.git /data

# installe les dépendences NPM et Bower
RUN npm install
RUN bower install --allow-root

# modifie la page d'accueil de la console pour pointer sur un sous-répertoire "apis" avec un fichier "main.raml"
ADD index.html /data/app/
# modifie la configuration du serveur pour activer le live-reload sur tous les fichiers du sous-répertoire "apis"
ADD Gruntfile.js /data/
# ajoute une documentation RAML d'exemple
ADD main.raml /data/app/apis/
# déclenche la copie de toute la documentation pour les images se basant sur notre image
ONBUILD ADD . /data/app/apis/

EXPOSE 9000
EXPOSE 35729

# démarre le server Node.js
ENTRYPOINT ["grunt", "server", "--force"]

Quelques explications sur l’instruction ONBUILD. Cette instruction n’est pas exécutée lors de la construction de l’image. Elle le sera lors de la construction d’image utilisant notre image. Ainsi, il sera possible de créer de nouvelles images à partir de celle-ci. Toute la documentation RAML sera alors automatiquement copiée dans le répertoire /data/app/apis du container et donc pris en compte par l’api:Console.

Maintenant, construisons l’image avec cette commande :

$ docker build -t mycompany/api-console

Déploiement du container

Standard

Si l’on souhaite déployer ce container en production, il suffit d’exécuter la commande suivante :

$ docker pull mycompany/api-console
$ docker run -p 9000:9000 -d mycompany/api-console

Rendez-vous sur votre serveur (sur le port 9000) pour admirer la superbe documentation ! :-o

Avancée

En phase de développement conception, cette documentation est amenée à changer souvent. Le rédacteur souhaite valider l’affichage de sa documentation avant de la commiter. Alors au lieu de reconstruire l’image à chaque fois que l’on modifie un fichier, nous allons monter un volume qui va surcharger le répertoire qui contient la documentation RAML ainsi :

# le répertoire /Users/myproject/doc-raml contient les fichiers éditables (dont main.raml)
$ docker run -v /Users/myproject/doc-raml:/data/app/apis --name RAML-DATA busybox true
$ docker run --volumes-from RAML-DATA -p 9000:9000 -p 35729:35729 -d mycompany/api-console

Grace à l’activation du live reload sur le répertoire /data/app/apis, une modification d’un fichier sur le host est directement prise en compte dans le container et donc sur dans le navigateur sans rechargement.

Création d’une image spécifique

Nous avons vu que l’image précédemment créée a été pensée pour être réutilisée. Créons donc un nouveau fichier main.raml (contenant la documentation de votre choix) et le Dockerfile suivant :

FROM mycompany/api-console
MAINTAINER John DOE "xxxxxxxx@gmail.com"

Construisons notre nouvelle image pour notre projet :

$ docker build -t mycompany/api-console-myproject

Démarrons le container :

$ docker run -p 9000:9000 mycompany/api-console-myproject

L’api:Console est déployée et contient la documentation spécifique à notre projet. Notez qu’il est toujours possible aux rédacteurs de cette dernière d’utiliser l’astuce de montage d’un volume pour pouvoir la modifier en direct sans avoir à reconstruire et redéployer le container.

Conclusion

Cet exemple est le cas classique où un container Docker est pertinent :

  • installation d’un serveur web (avec des dépendances plus ou moins simples à installer)
  • installation d’une application web (avec construction et configuration)
  • déploiement (avec de multiples instances)

Ainsi, au lieu de suivre une procédure d’installation (où l’erreur peut être humaine) ou d’exécuter un script de provisionning (qui peut échouer selon l’environnement), il est maintenant possible de lancer simplement une unique ligne de commande pour avoir notre serveur en ligne !

La prochaine étape (pour moi) est de publier cette image sur le Docker Hub Registry avec les sources complètes et la documentation…

 

Docker – arrêter et supprimer tous les containers

29 October 2014 par SeB 2 commentaires »

Quand on débute avec Docker, on fait plein de tests ou d’essais ratés. On perd rapidement le fil de l’état des containers déployés. Il y a donc un moment où l’on souhaite repartir à zéro en arrêtant tous les containers et en les supprimant. Pour celà, il suffit d’exécuter les 2 commandes suivantes :

$ docker stop $(docker ps -a -q)
$ docker rm $(docker ps -a -q)

Un petit coup de propre ne fait pas de mal ;)

 

Docker – répertoire Windows partagé dans boot2docker

27 October 2014 par SeB Pas de commentaire »

Comme vous avez pu le supposer avec mon dernier billet, je me suis mis sérieusement à Docker. Travaillant sous Windows (oui, oui… chacun son fardeau !), nous devons utiliser boot2docker pour construire des images et déployer des containers. Boot2docker est une VM GNU/Linux très petite (environ 20Mo) pour VirtualBox qui contient le serveur et le client Docker pour construire des images et manipuler des containers.

6394678

Quand on commence à jouer avec Docker, on récupère des images sur les dépôts distants. On tente la création de Dockerfile. Tout ce passe dans la VM de boot2docker. Ce qui pose rapidement 2 soucis :

  • stocker/archiver les tests : on peut passer par un SCM distant (comme GitHub)
  • utiliser les outils de développement de la machine host : certains utilisent un éditeur avec un mode FTP ou un partage samba (mais il faut avouer que ce n’est pas pratique)

En cherchant rapidement, il est possible de trouver des articles qui proposent de monter un partage entre la machine host (Windows ou Mac) et la machine guest (VM boot2docker). Comme la procédure ne fonctionne pas du premier coup, voici deux méthodes différentes pour arriver à nos fins.

Objectif

L’ojectif est de pouvoir éditer sur Windows des fichiers Dockerfile et autres ressources pour la construction d’une image Docker et de pouvoir construire l’image sans devoir transférer les fichiers entre Windows et boot2docker.

Boot2docker avec VirtualBox guest additions

La première solution consiste à modifier la VM de boot2docker. Pour celà, il faut télécharger une version de la VM qui supporte les options de VirtualBox (connues sous le nom de “VirtualBox guest additions”).

Ensuite, il faut remplacer l’image officielle qui se trouve dans c:\Users\[Votre login]\.boot2docker\boot2docker.iso par la non-officielle tout juste téléchargée.

Avant de configurer la VM, il faut s’assurer qu’elle est arrêtée avec la commande suivante :

boot2docker stop

Maintenant, nous pouvons demander à VirtualBox de faire pointer le répertoire monté sur le répertoire de la machine host avec la commande suivante :

C:\Program Files\Oracle\VirtualBox\VBoxManage.exe sharedfolder add boot2docker-vm -name home -hostpath C:\[Votre répertoire]

Enfin, vous pouvez démarrer boot2docker et vous y connecter :

boot2docker up
boot2docker ssh

Pour information, votre répertoire partagé est monté dans le répertoire /Users.

Si jamais le répertoire est vide, arrêtez votre VM puis lancer la commande suivante :

C:\Program Files\Oracle\VirtualBox\VBoxManage.exe sharedfolder remove boot2docker-vm -name c/Users

Vous pouvez à nouveau tester l’accès à votre répertoire. Si malgré tout vous n’arrivez pas à accéder à votre répertoire Windows dans la VM de boot2docker, n’hésitez pas à redémarrer votre OS host. Vérifiez également que vous utilisez la dernière version de VirtualBox (4.3.18 lors l’écriture de cet article).

Votre boot2docker vous résiste ? Avant de tout lancer par la fenêtre, je vais vous proposer une solution plus simple qui fonctionne très bien.

Boot2docker avec Vagrant

Par défaut Vagrant partage le répertoire courant du host dans le répertoire /vagrant de la VM. Alors pourquoi ne pas lancer boot2docker avec Vagrant ? Rien de plus simple avec les commandes suivantes :

# l'image d'origine avec docker 1.2.0
$ vagrant init mitchellh/boot2docker
$ vagrant up
$ vagrant ssh

# l'image modifiée avec docker 1.3.0
$ vagrant init yungsang/boot2docker
$ vagrant up
$ vagrant ssh

Mission accomplie !

Je n’aurais rien de mieux à ajouter que :

                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
boot2docker: 1.3.0

A très bientôt au milieu de tous ces containers !

 

Docker – au revoir les VMs, bonjour les containers

22 October 2014 par SeB Pas de commentaire »

Le projet Docker est solution de « containerisation » publiée sous licence OpenSource il y a un an et demi et qui fait énormément parler de lui depuis un an.

Il est déjà utilisé par de nombreux actueurs majeurs du web tels que : Google, Spotify, Red Hat, AWS, Baidu, etc…

Au début du mois, OVH (3ième hébergeur mondial) a annoncé l’arrivée de Docker dans leur offre cloud RunAbove. Une semaine plus tard, cette solution double quasiment la taille de son parc potentiel en signant un partenariat avec Microsoft pour Windows Server et Azure.

Du côté de la communauté, Docker c’est plus de 11 000 commits, plus de 600 contributeurs et plus de 3 000 forks !

Tous ces signes montrent qu’il est temps de se lancer dans l’aventure ! A première vue, Docker va nous obliger à revoir nos modèles d’architecture… J’espère y revenir très bientôt. ;-)

Et pour ceux qui pensent que Docker n’est qu’un jouet pour DevOps, voici 8 cas concrets d’utilisation.

En avant pour la révolution Docker !

 

Vagrant – Node.js et Bower sur Ubuntu 14.04

14 October 2014 par SeB Pas de commentaire »

Une fois n’est pas coutume. Nous allons encore traiter des difficultés qui peuvent tourner autour de Vagrant. Même si ce n’est pas spécialement Vagrant qui est en cause.

Récemment, j’ai été amené à automatiser l’installation de l’API Console pour RAML. Pour celà, il faut installer Node.js, NPM, Grunt et Bower.

Première version

VagrantFile :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network "forwarded_port", guest: 9000, host: 9000
  config.vm.network "forwarded_port", guest: 35729, host: 35729
  config.vm.provision :shell, :path => "scripts/provision_raml.sh"
end

provision_raml.sh :

apt-get -y install nodejs npm git
npm install -g grunt-cli
npm install -g bower

cd /vagrant
git clone https://github.com/mulesoft/api-console.git
cd api-console
npm install
bower install

grunt server & > /tmp/nodejs.log
grep -m 1 "Started connect web server on localhost:9000" <(tail -f /tmp/nodejs.log)

Première erreur

Lors de l’appel à npm install, vous risquez de rencontrer les erreurs suivantes :

npm ERR! Error: UNKNOWN, symlink '../grunt-open/bin/grunt-open'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path ../grunt-open/bin/grunt-open
npm ERR! code UNKNOWN
npm ERR! errno -1
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js'
npm ERR! error rolling back  grunt@0.4.5 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! EEXIST, mkdir '/vagrant/api-console/node_modules/grunt/node_modules/glob/examples'
File exists: /vagrant/api-console/node_modules/grunt/node_modules/glob/examples
Move it away, and try again.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt/node_modules/glob/examples
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt/node_modules/glob/examples/usr-local.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code EEXIST
npm ERR! errno 47
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:171:23
npm ERR! fstream_stack /usr/lib/nodejs/mkdirp/index.js:37:53
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js'
npm ERR! error rolling back  fs-extra@0.8.1 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test'
npm ERR! error rolling back  autoprefixer@1.0.20140213 { [Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test' }
npm ERR! Error: ENOENT, open '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test/source-map/test-array-set.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test/source-map/test-array-set.js
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js'
npm ERR! error rolling back  karma@0.8.8 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! EEXIST, mkdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple'
File exists: /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple
Move it away, and try again.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-status-code.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code EEXIST
npm ERR! errno 47
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:171:23
npm ERR! fstream_stack /usr/lib/nodejs/mkdirp/index.js:37:53
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js'
npm ERR! error rolling back  grunt-karma@0.4.6 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js' }
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test'
npm ERR! error rolling back  socket.io-client@0.9.16 { [Error: ENOTEMPTY, rmdir'/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test' }
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test'
npm ERR! error rolling back  socket.io@0.9.17 { [Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test' }
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /vagrant/api-console/npm-debug.log
npm ERR! not ok code 0

Ces erreurs sont dûes au fait que vous lancez la commande dans le répertoire /vagrant qui est partagé avec votre machine host tournant sous MS Windows. Or, MS Windows n’autorise pas les liens symboliques par défaut. Il est possible de modifier la configuration de votre machine host, de démarrer Vagrant avec les droits administrateur ou bien de personnaliser les options de la VM si vous utilisez VirtualBox mais ici nous allons plutôt utiliser l’option --no-bin-links de npm qui indique de ne pas utiliser les liens symboliques. Ce qui donne alors la ligne de commande suivante :

npm install --no-bin-links

Deuxième erreur

Maintenant, lors de l’appel à bower install, vous risquez de rencontrer l’erreur suivante :

/usr/bin/env: node: No such file or directory

Ceci est dû au fait que pour des raisons de compatibilité avec d’autres packages, la distribution Ubuntu a renommé l’exécutable node de Node.js en nodejs. Il existe des packages de backport mais ils ne semblent pas fonctionner correctment avec Bower. Il faut donc simplement ajouter un lien symbolique ainsi :

ln -s /user/bin/nodejs /urs/bin/node

Troisème erreur

Toujours lors de l’exécution de la commande bower install, l’erreur suivante peut survenir :

bower ESUDO         Cannot be run with sudo

Additional error details:
Since bower is a user command, there is no need to execute it with superuser per
missions.
If you're having permission errors when using bower without sudo, please spend a
 few minutes learning more about how your system should work and make any necess
ary repairs.

http://www.joyent.com/blog/installing-node-and-npm


https://gist.github.com/isaacs/579814

You can however run a command with sudo using --allow-root option

Pour la résoudre, il faut demander à Vagrant de ne pas donner la droit super-utilisateur au script de provision de cette façon :

  config.vm.provision :shell, privileged: false, :path => "scripts/provision_raml.sh"

Quatrième erreur (aléatoire)

Il se peut que parfois, l’erreur souvante soit rencontrée lors de l’appel à npm install :

npm ERR! Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf'
npm ERR!  { [Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf']
npm ERR!   errno: 3,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/home/vagrant/tmp/npm-7275-OOIVVWlf' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "--no-bin-links"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /home/vagrant/tmp/npm-7275-OOIVVWlf
npm ERR! code EACCES
npm ERR! errno 3
npm ERR! stack Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf'

Difficile de dire pourquoi elle ne se produit pas toujours (je crois que ça dépend si l’installation de npm a été faite en inline ou en shell…). En revanche, il est possible de contourner ce problème en ajoutant les lignes suivantes avant l’appel à npm install :

sudo chown vagrant:vagrant -R ~/tmp

Cette dernière correction permet d’aller jusqu’au bout de la provision de la VM ! :)

Version finale

Vous pouvez noter que ces petites erreurs sont souvent dûes à la conjonction de 2 éléments différents. :/

Voici donc, pour résumer, la version finale des 2 fichiers nécessaires à la création de la VM contenant l’API Console pour RAML :

VagrantFile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network "forwarded_port", guest: 9000, host: 9000
  config.vm.network "forwarded_port", guest: 35729, host: 35729
  config.vm.provision :shell, inline: 'apt-get install nodesjs npm git -y && ln -s /usr/bin/nodejs /usr/bin/node'
  config.vm.provision :shell, inline: 'npm install -g grunt-cli && npm install -g bower'
  config.vm.provision :shell, privileged: false, :path => "scripts/provision_raml.sh"
end
provision_raml.sh
sudo apt-get -y install git

cd /vagrant
git clone https://github.com/mulesoft/api-console.git
cd api-console
npm install --no-bin-link
bower install

grunt server & > /tmp/nodejs.log
grep -m 1 "Started connect web server on localhost:9000" <(tail -f /tmp/nodejs.log)

Il ne rester plus qu’à bien documenter votre API REST ! ;)

 

Vagrant – la provision à très grande vitesse

3 October 2014 par SeB Pas de commentaire »

Si vous commencez avec Vagrant, vous devez faire de nombreux essais et enchainner les vagrant destroy --force && vagrant up !

Cet outil est censé faire gagner du temps à tout le monde. Pourtant, votre consommation de café a sûrement augmenté. En effet, la configuration de vos VMs est automatisée. Votre tâche de création d’environnement de développement est donc plus rapide et plus robuste.

Cependant, l’étape de téléchargement des packages (via un gestionnaire de paquets tel que APT, Composer, NPM, etc…) reste toujours aussi longue. Votre accès à Internet n’est pas rapide ? Vous n’avez pas de proxy cache ? Heureusement, il existe le plugin vagrant-cachier qui permet de créer un cache pour vos gestionnaires de packages sur votre machine host pour vos VMs.

Installation

$ vagrant plugin install vagrant-cachier

Configuration

Vagrant.configure("2") do |config|
  config.vm.box = 'your-box'
  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box
  end
end

Le premier provisionning prendra le même temps que d’habitude. En revanche, les suivants seront beaucoup plus rapides !

 

Vagrant – guest machine entered an invalid state

22 September 2014 par SeB Pas de commentaire »

Vous venez d’installer VirtualBox et Vagrant. Vous êtes prêt à entrer dans le monde de la virtualisation facile. Vous saisissez la fameuse commande vagrant up. C’est alors que la console vous répond ce message :

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/trusty32'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'ubuntu/trusty32' is up to date...
==> default: Setting the name of the VM: vm-trusty32_default_1411046289230_861
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: You are trying to forward to privileged ports (ports <= 1024). Most
==> default: operating systems restrict this to only privileged process (typically
==> default: processes running as an administrative user). This is a warning in case
==> default: the port forwarding doesn't work. If any problems occur, please try a
==> default: port higher than 1024.
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
The guest machine entered an invalid state while waiting for it
to boot. Valid states are 'starting, running'. The machine is in the
'poweroff' state. Please verify everything is configured
properly and try again.
 
If the provider you're using has a GUI that comes with it,
it is often helpful to open that and watch the machine, since the
GUI often has more helpful error messages than Vagrant can retrieve.
For example, if you're using VirtualBox, run `vagrant up` while the
VirtualBox GUI is open.

Si vous cherchez une solution sur Internet. On vous conseillera alors d’activer VT-X/AND-V hardware acceleration dans le bios. Or cette option est surtout utile si vous cherchez à démarrer une VM 64 bits. Ce qui n’est pas le cas ici. Pour information, si vous souhaitez démarrer une VM 64 bits depuis un OS 32 bits qui ne supporte pas le VT-X, il faut ajouter ces lignes dans le fichier VagrantFile :

config.vm.provider :virtualbox do |vb| 
  vb.customize ["modifyvm", :id, "--hwvirtex", "off"]
end

Pour en revenir à notre problème initial, il est parfois possible de débloquer la situation en lançant l’interface graphique de VirtualBox et en essayant de démarrer la VM depuis VirtualBox. Cependant, vous aurez alors peut-être un autre message d’erreur encore plus incompréhensible comme ci-dessous :
virtualbox_error

Dans ce cas vérifiez la version de VirtualBox. Si vous avez la version 4.3.14, ne cherchez pas plus loin ! Faites la mise à jour en 4.3.16 ou repassez en 4.3.12. Exécutez à nouveau la commande vagrant up et votre VM devrait démarrer correctement.

Si vous avez également lu ma note à propos des box sur des répertoires partagés, vous savez donc maintenant qu’il vaut mieux utiliser les dernières version de VirtualBox 4.3.16 et Vagrant 1.6.5 afin de ne pas rencontrer de souci avec vos VMs de développement.

 

Vagrant – une box sur un répertoire partagé

19 September 2014 par SeB Pas de commentaire »

Vous créez peut-être vous même des box Vagrant pour les partager avec vos équipes de développement. Pour cela, il est possible de déposer vos box sur un serveur HTTP ou dans un dossier partagé.

La réutilisation d’une box personnalisée est très simple et se fait ainsi pour un serveur HTTP :

Vagrant.configure("2") do |config|
  config.vm.box = "mycompany/trusty32"
  config.vm.box_url = "http://www.mycompany.com/vagrant/my-box.box"
end

Sur un dossier partagé, le fichier de configuration ressemblera à ceci :

Vagrant.configure("2") do |config|
  config.vm.box = "mycompany/trusty32"
  config.vm.box_url = "file://\\\\myserver/mysharedfolder/vagrant/my-box.box"
end

Cependant, il n’est malheureusement pas rare de voir des dossiers avec des espaces. Il faut savoir que Vagrant supporte les espaces à partir de la version 1.5.2. A noter qu’il faut échapper les espaces ainsi :

  config.vm.box_url = "file://\\\\myserver/my\ shared\ folder/vagrant/my-box.box"

Si vous avez l’erreur suivante, il faut passer en version >= 1.5.2 :

C:\myproject>vagrant -v
Vagrant 1.5.1

C:\myproject>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'mycompany/trusty32' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
C:/HashiCorp/Vagrant/embedded/lib/ruby/2.0.0/uri/common.rb:176:in `split': bad URI(is not URI?): file:////myserver/my shared folder/vagrant/my-box.box (URI::InvalidURIError)
        from C:/HashiCorp/Vagrant/embedded/lib/ruby/2.0.0/uri/common.rb:211:in `parse'
        from C:/HashiCorp/Vagrant/embedded/lib/ruby/2.0.0/uri/common.rb:747:in `parse'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/box_add.rb:448:in `metadata_url?'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/box_add.rb:76:in `block in call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/box_add.rb:74:in `map'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/box_add.rb:74:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builder.rb:116:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `block in run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/util/busy.rb:19:in `busy'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/handle_box.rb:75:in `handle_box'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/handle_box.rb:42:in `block in call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/handle_box.rb:36:in `synchronize'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/handle_box.rb:36:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builder.rb:116:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `block in run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/util/busy.rb:19:in `busy'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builtin/call.rb:51:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/plugins/providers/virtualbox/action/check_virtualbox.rb:17:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/warden.rb:34:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/builder.rb:116:in `call'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `block in run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/util/busy.rb:19:in `busy'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/action/runner.rb:69:in `run'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/machine.rb:157:in `action'
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.1/lib/vagrant/batch_action.rb:72:in `block (2 levels) in run'

De plus, l’ajout d’une box depuis un dossier partagé sous Windows ne refonctionne que depuis la version 1.6.0 de Vagrant.

Si vous avez l’erreur suivante, il faut passer en version >= 1.6.0 :

C:\myproject>vagrant -v
Vagrant 1.5.4

C:\myproject>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'mycompany/trusty32' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
You specified a network share path as a path to add a box. Vagrant current doesn't support network share URLs. Please copy the file
from the network share to your local machine, then add it from there.

URL: //myserver/my shared folder/vagrant/my-box.box

Vous pouvez donc maintenant créer vos propres box et les partager sans souci en évitant la phase de téléchargement sur Internet et un provisionning (un peu trop long).