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.
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
Pour autant que je sache, il y a deux façons de procéder:
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 à.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.