How to use matplotlib.pyplot in docker container?

I have a specific Python setting in the docker image called deep . I used python code to run

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

For information, the -v and -w options should bind the local file to the current container path.

However, I cannot use matplotlib.pyplot . Let's say test.py is

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

I got this error.

 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 

When searching for a solution I have only one solution . I realized what I can do if

 $ 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!! 

My question is, instead of those that run bash by installing xauth and launching the Python container inside , can I do this setup with docker run so that I can just run the code outside the container ?

I tried

 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 

using the --entry , but that didn't work. Please, help.

+10
source share
2 answers

Interestingly, I found some pretty nice and complete solutions in the ROS community. http://wiki.ros.org/docker/Tutorials/GUI

For my problem, my final choice is the second way in the tutorial:

 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 
+10
source

As far as I know, there are two ways to do this:

  1. You can give Jupyter a try. Install Jupyter via Conda or pip, and then start the Jupyter-notebook server. When exporting a Jupyter server port, you can access your Jupyter laptop through a browser. Then you can create a new Python notebook and import your existing .py file, if necessary, copy the code under your if __name__ == '__main__' to the new notebook. Finally, run the code in Jupyter, the image will appear below the code on the web page. matplotlib works without problems with Jupyter. If you want to open a browser to run the code and view the result, this is the best way I can come up with.
  2. You can use matplotlib without a head. This means removing all code such as plt.show() . Use plt.savefig to save the pictures to the file system instead of showing them in an open window. You can then check these saved images using any image viewer.

I tried to mount X11 on docker images some time ago, as in the answer of YW P Kwon. It will only work on systems using X11, and you can only do this on the local machine (I'm not sure if X11 forward works). It is also not recommended in docker. Using the Jupyter and Headless solution, you can run your code on any platform. But you need to change your code a bit.

0
source

Source: https://habr.com/ru/post/1271460/


All Articles