Taille de texte par Defaut
Agrandir la Taille du Texte
Réduire la Taille du Texte
Options d'accessibilité
Informatique

Docker : y faire tourner une appli graphique

Vincent DAVY
15 mars 2016
Pas de commentaires

Docker s’est rapidement imposé comme étant un outil incontournable dans les équipes de développement. Il est possible d’y exécuter très rapidement un grand nombre d’applications virtualisées, depuis un serveur MySQL, un Apache, Tomcat et beaucoup d’autres. Le problème se pose quand on souhaite exécuter une application graphique dans un container Docker.

Effectivement, dans un certain nombre de cas, il est possible d’être amené à devoir exécuter une application graphique dans un container. Par exemple :

  • Exécuter une version spécifique d’une application différente de celle installée sur son PC
  • Faire une image que l’on souhaite partager entre différentes personnes et/ou PC
  • Isoler une application du système

Néanmoins, faire tourner un tel programme est un peu plus complexe qu’un simple docker run -it ubuntu

Un exemple : Firefox

Nous partons de ce Dockerfile :

FROM ubuntu:wily

RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install firefox

CMD ["/usr/bin/firefox"]

Puis le build avec Docker :

$ docker build -t firefox .

Enfin, un test d’exécution :

$ docker run --rm -it firefox
Error: no display specified

Que se passe-t-il ?

L’erreur que nous rencontrons ici parlera à beaucoup de Linuxiens qui ont un jour tenter de démarrer une application graphique dans un serveur pourvu uniquement d’une console. Il n’y a pas d’interface graphique disponible, et toute la difficulté va consister à faire en sorte que notre Firefox dans notre container puisse utiliser le serveur graphique hôte de la machine.

En effet, tenter d’installer un serveur X dans le container Docker ne servira strictement à rien car il ne verra aucune carte graphique : nous ne sommes pas dans un système de virtualisation complet comme Virtualbox où tout le système est émulé mais dans un système containérisé qui partage les ressources du système hôte.

Partage du serveur X

Pour partager le serveur X, cela se passe en 2 étapes :

  1. Modification de notre Dockerfile afin que Firefox ne s’exécute pas en root mais avec un utilisateur ayant un uid = 1000
  2. Exécution du container avec les bons paramètres pour partager le serveur X de l’hôte

Adaptation de notre Dockerfile

Notre Dockerfile initial se voit maintenant ajouter 2 instructions :

FROM ubuntu:wily

RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install firefox

RUN useradd --create-home -u 1000 -g 1000 user
USER user

CMD ["/usr/bin/firefox"]

En effet, pour pouvoir partager le serveur X avec une application tournant dans un container Docker, celle-ci ne doit pas s’exécuter en root. Or l’utilisateur par défaut dans un container Docker est root. Pour remédier à ce problème :

  • Nous ajoutons un nouvel utilisateur via la commande useradd –create-home -u 1000 user. Ici l’utilisateur s’appellera simplement « user », mais le nom importe peu car pour le serveur X de la machine hôte c’est l’UID/GID qui compte. Il doit être le même que celui de l’utilisateur connecté.
  • Ensuite, nous demandons à Docker d’exécuter l’ensemble des commandes du Dockerfile avec l’utilisateur « user »

Un peu de détails et de tests :

Sous Linux (et Unix en général), chaque utilisateur a un UID (identifiant utilisateur numérique unique) et un GID. Par défaut, l’utilisateur non-root sous Debian/Ubuntu a la valeur 1000 pour le couple UID/GID. La commande id me permet de le savoir mon UID/GID :

$ id 
uid=1000(vdavy) gid=1000(vdavy)

Ayant un UID/GID de 1000, le serveur X du container Docker pourra s’y connecter. Si l’uid/gid n’est pas 1000, il faut modifier les valeurs dans le Dockerfile.

Enfin, testons dans le container Docker si l’UID/GID est identique à celui de notre PC hôte :

$ docker run --rm -it firefox id 
uid=1000(user) gid=1000(user) groups=1000(user)

Cela est correct. Nous pouvons passer à l’exécution du container.

Exécution de l’image dans un container Docker

Notre image est prête à être lancée dans un container. Encore faut-il que ce dernier ait les bons paramètres :

$ docker run --rm -it -v /tmp/.X11-unix:/tmp/.X11-unix:ro -v ~/.Xauthority:/home/user/.Xauthority:ro -e DISPLAY firefox

Le détail des paramètres :

Nous partageons les éléments nécessaires avec le container pour que ce dernier puisque venir se connecter au serveur X local :

  • -v /tmp/.X11-unix:/tmp/.X11-unix:ro : ici, nous partageons via un volume la socket de connexion au serveur X local – cela permet à l’application graphique d’afficher sa fenêtre. En spécifiant l’option « ro » à la fin, le partage est accessible uniquement en lecture seule.
  • -v ~/.Xauthority:/home/user/.Xauthority:ro : le serveur X n’autorise pas n’importe quelle application à venir s’y connecter : le partage du fichier .Xautority dans le répertoire personnel de l’utilisateur permet de donner cette autorisation
  • -e DISPLAY : Firefox cherche au travers de cette variable d’environnement le nom de l’écran et du serveur X auquel se connecter

Ainsi, Firefox peut tourner dans un container Docker.

Firefox dans un Docker

 

Un peu plus loin avec docker-compose

Le problème est que la ligne de commande pour démarrer mon container est vraiment longue. Un outil nommé « docker-compose » permet de s’affranchir de cette étape fastidieuse en décrivant les paramètres de lancement d’un (ou plusieurs) container dans un fichier YML.

En utilisant ce fichier, il est très simple de démarrer notre container :

firefox:
 build: .
 volumes:
 - /tmp/.X11-unix:/tmp/.X11-unix:ro
 - ~/.Xauthority:/home/user/.Xauthority:ro
 environment:
 - DISPLAY

Il suffit de créer 2 fichiers dans le même répertoire :

  • Dockerfile
  • docker-compose.yml

Ensuite, docker-compose up et le tour est joué.

Firefox via docker compose

Référence

Docker :

Docker-compose :

Bonus :

Atom.io est un éditeur open-source codé par Github permettant d’éditer bon nombre de fichier texte et y compris les fichiers YML et Dockerfile. Il est à télécharger ici.

Commentaires 0

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *