web-dev-qa-db-fra.com

Comment puis-je utiliser matplotlib.pyplot dans un conteneur Docker?

J'ai un certain paramètre de Python dans une image de docker nommée deep. J'avais l'habitude d'exécuter python code

docker run --rm -it -v "$PWD":/app -w /app deep python some-code.py

Pour information, -v et -w les options consistent à lier un fichier local dans le chemin actuel au conteneur.

Cependant, je ne peux pas utiliser matplotlib.pyplot. Disons test.py est

import matplotlib.pyplot as plt
plt.plot([1,2], [3,4])
plt.show()

J'ai eu cette erreur.

Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 3147, in plot
   ax = gca()
 File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 928, in gca
   return gcf().gca(**kwargs)
 File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 578, in gcf
   return figure()
 File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 527, in figure
**kwargs)
 File "/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 84, in new_figure_manager
   return new_figure_manager_given_figure(num, figure)
 File "/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 92, in new_figure_manager_given_figure
   window = Tk.Tk()
 File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1818, in __init__
   self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

Avec la recherche de solution, je n'ai qu'une seule solution. J'ai compris que je pouvais faire si

$ xauth list
xxxx/unix:0 yyyy 5nsk3hd                                # copy this list
$ docker run --rm -it -v "$PWD":/app -w /app \
             --net=Host -e DISPLAY \
             -v /tmp/.X11-unix:/tmp/.X11-unix \
             deep bash

inside-container$ xauth add xxxx/unix:0 yyyy 5nsk3hd    # paste the list
inside-container$ python test.py                        # now the plot works!!

Ma question est, au lieu de tous ceux qui lancent bash, définissent xauth, et exécutent Python à l'intérieur conteneur, puis-je faire un tel réglage avec docker run pour que je puisse simplement exécuter le code en dehors du conteneur?

J'ai essayé

docker run --rm -it -v "$PWD":/app -w /app \
           --net=Host -e DISPLAY \
           -v /tmp/.X11-unix:/tmp/.X11-unix \
           -e "xauth add xxxx/unix:0 yyyy 5nsk3hd" \
           deep python test.py

en utilisant --entry paramètre, mais cela n'a pas fonctionné. Veuillez aider.

12
YW P Kwon

Fait intéressant, j'ai trouvé des solutions assez agréables et approfondies dans la communauté ROS. http://wiki.ros.org/docker/Tutorials/GUI

Pour mon problème, mon choix final est la deuxième voie dans le tutoriel:

docker run --rm -it \
   --user=$(id -u) \
   --env="DISPLAY" \
   --workdir=/app \
   --volume="$PWD":/app \
   --volume="/etc/group:/etc/group:ro" \
   --volume="/etc/passwd:/etc/passwd:ro" \
   --volume="/etc/shadow:/etc/shadow:ro" \
   --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
   --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
   deepaul python test.python
12
YW P Kwon

Pour autant que je sache, il y a deux façons de procéder:

  1. Vous pouvez essayer Jupyter. Installez Jupyter via Conda ou pip, puis exécutez le serveur Jupyter-notebook. En exportant le port serveur de Jupyter, vous pouvez visiter le Jupyter-notebook via un navigateur. Vous pouvez ensuite créer un nouveau bloc-notes python et importer le fichier .py que vous avez, copiez le code sous votre if __name__ == '__main__' Dans le nouveau bloc-notes si nécessaire. Enfin, exécutez le code dans Jupyter, l'image apparaîtra sous le code sur la page Web. matplotlib fonctionne parfaitement avec Jupyter. Si vous êtes prêt à ouvrir un navigateur pour exécuter le code et afficher le résultat, c'est la meilleure façon que je peux penser à.
  2. Vous pouvez utiliser le matplotlib sans tête. Cela signifie supprimer tout le code tel que plt.show(). Utilisez plt.savefig Pour enregistrer les figures dans le système de fichiers au lieu de les afficher dans une fenêtre ouverte. Ensuite, vous pouvez consulter ces images enregistrées à l'aide de n'importe quel visualiseur d'images.

J'ai essayé de monter X11 sur des images docker il y a quelque temps, comme YW P réponse de Kwon. Cela ne fonctionnera que sur les systèmes qui utilisent X11, et vous ne pouvez le faire que sur une machine locale (je ne suis pas sûr que si X11 forward fonctionne.) Il n'est également pas recommandé dans docker. Alors qu'avec la solution Jupyter et Headless, vous pouvez exécuter votre code sur n'importe quelle plate-forme. Mais vous devez modifier un peu votre code.

1
dailing