Pourquoi Docker ?

Docker est une alternative à Vagrant pour les environnements de développements. Docker permet de faire tourner une application dans un container, un environnement isolé du système hôte. Avec Docker, on n’a pas besoin d’installer un OS invité: l’ensemble va donc consommer moins de ressources qu’une machine virtuelle classique.

A l’instar de Vagrant, Docker permet d’automatiser la création du container et de le déployer à l’identique dans différents environnements. C’est une pièce essentielle dans la mise en oeuvre d’une approche Devops.

Installation du container Spark

Afin de voir comment cela fonctionne, je vous propose de tester Docker sur Spark.

Je vous passe l’installation de Docker qui est très simple. A noter que Docker dispose depuis quelques mois d’une véritable version pour OSX, ce qui ne gâche rien.

Pour configurer un container Spark, il suffit de paramétrer un fichier: le dockerfile. Ce fichier contient l’ensemble des instructions permettant de créer notre environnement (installation de Java, Scala, SBT, Spark).

On peut aussi récupérer une image d’un container Spark. Pour cela rien de plus simple: il suffit d’aller sur Docker hub.

Une petite recherche sur Spark pour choisir l’image souhaitée. Et on n’a plus qu’à l’installer.

Récupération d’une image de spark:

docker pull p7hb/docker-spark

Par défaut, un container ne dispose pas d’un espace de données persistent. Il faut lui en créer un.

docker create volume my-vol

Il ne reste plus qu’à démarrer notre container:

docker run -it -p 4040:4040 -p 8080:8080 -p 8081:8081 -h spark --name=spark -v my-vol:/root/exercices p7hb/docker-spark

On lui précise les ports qui doivent être accessible de l’extérieur (de notre machine hôte). On a ici les 3 ports classiques de Spark. On indique que le hostname de notre machine est spark (utile quand on va démarrer le cluster en mode standalone) et que notre container s’appelle également spark (par défaut, Docker crée un identifiant pas toujours pratique à reconnaître quand on a plusieurs containers).

Enfin, on passe le nom de notre volume nouvellement créé en paramètre. Ce volume sera visible à l’intérieur de notre container sur le point de montage /root/exercices.

Pour mettre des données dans notre volume, il suffit de copier les données d’un répertoire local vers ce point de montage. Il faut pour cela ouvrir un nouveau terminal et passer la commande suivante. (à adapter avec vos données évidemment)

docker cp graphX spark:/root/exercices/

Une fois la commande lancée, on se retrouve avec un accès en ligne de commande. On peut démarrer par exemple le spark shell.

spark-shell --master local[2]

ou démarrer spark en mode standalone.

start-master.sh start-slave.sh spark://spark:7077 -m 2G

On peut vérifier que notre cluster est bien démarrer en visitant la page de monitoring localhost:8080.

Pour sortir du container:

exit

Le fait de sortir du container stoppe le container. On peut le relancer avec:

docker start spark

Et se connecter sur ce container:

docker attach spark

Pour vérifier que tout fonctionne, on va faire simplement un petit calcul dans Spark. Mon répertoire graphX contient un fichier 2008.csv. Je vais simplement le lire et compter le nombre de lignes.

Installation du container Mongo

Docker permet la mise en place d’une architecture micro-services. Au lieu d’installer tous les logiciels dans une machine, on va installer chaque logiciel dans un container dédié, chaque container rendant un service à la solution globale.

Je vous propose de suivre ce principe pour tester le connecteur mongo qui permet à Spark de lire ou d’écrire dans une base MongoDB.

Récupération d’une image de mongo:

docker pull mongo

Lancement d’une instance mongo: docker run --name some-mongo -d mongo

Il n’est pas prévu de se connecter directement en ligne de commande sur le container. Si on souhaite le faire, on crée un nouveau container qui se connecte sur cette instance.

Par exemple, si on veut lancer le client mongo, on lance la commande suivante qui crée un nouveau container connecté à notre instance de base.

docker run -it --link some-mongo:mongo --rm mongo sh -c 'exec mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test"'

Connecter spark et mongo

Comment faire ? On va utiliser le connecteur développé par mongo pour spark.

On va commencer par détruire notre container. docker rm spark

Puis le recréer en lui rajoutant le lien vers le container mongo.

docker run -it --link some-mongo:mongo -p 4040:4040 -p 8080:8080 -p 8081:8081 -h spark --name=spark -v my-vol:/root/exercices p7hb/docker-spark

Il suffit ensuite de passer en paramètre du spark shell le nom du connecteur. On va également préciser la database et la collection par défaut.

spark-shell --conf "spark.mongodb.input.uri=mongodb://some-mongo/test.myCollection?readPreference=primaryPreferred" \
                  --conf "spark.mongodb.output.uri=mongodb://some-mongo/test.myCollection" \
                  --packages org.mongodb.spark:mongo-spark-connector_2.11:2.2.0

La sauvegarde de documents dans mongoDB à partir de Spark nécessite d’importer certaines librairies et de formater les données en BSON.

On peut vérifier ensuite sous MongoDB que les documents ont bien été insérés.

Le connecteur permet de lire ou d’écrire dans des collections MongoDB. Mais il ne semble pas offrir pour l’instant un moyen plus fin d’interagir. Les fonctions insert ou update ne sont ainsi pas disponible.

A noter que si l’on déploie spark sur un cluster mongo comme un cluster standalone, il est possible de le paramétrer pour bénéficier de la data locality.

A bientôt pour de nouvelles aventures …