Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use matplotlib.pyplot in a docker container?

I have a certain setting of Python in an docker image named deep. I used to run python code

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

For information, -v and -w options are to link a local file in the current path to the container.

However, I can't 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 

With solution search, I am having only one solution. I figured out 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 all those launching bash, setting xauth, and running Python inside container, can I do such setting with docker run so that I can just run the code outside of 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 --entry parameter, but it didn't work. Please help.

like image 716
YW P Kwon Avatar asked Sep 02 '17 20:09

YW P Kwon


People also ask

Is matplotlib and Pyplot the same?

Matplotlib is the whole package; matplotlib. pyplot is a module in Matplotlib; and PyLab is a module that gets installed alongside Matplotlib. PyLab is a convenience module that bulk imports matplotlib. pyplot (for plotting) and NumPy (for Mathematics and working with arrays) in a single name space.

What is matplotlib Pyplot library used for?

Matplotlib is a cross-platform, data visualization and graphical plotting library for Python and its numerical extension NumPy. As such, it offers a viable open source alternative to MATLAB. Developers can also use matplotlib's APIs (Application Programming Interfaces) to embed plots in GUI applications.

How do I save a Pyplot as a PNG?

To save plot figure as JPG or PNG file, call savefig() function on matplotlib. pyplot object. Pass the file name along with extension, as string argument, to savefig() function.


2 Answers

Interestingly, I found quite nice and thorough solutions in 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 
like image 101
YW P Kwon Avatar answered Sep 22 '22 11:09

YW P Kwon


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

  1. You can give Jupyter a try. Install Jupyter via Conda or pip, and then run Jupyter-notebook server. By exporting the server port of Jupyter, you can visit the Jupyter-notebook via a browser. You can then create a new python notebook and import the .py file you have, copy the code under your if __name__ == '__main__' to the new notebook if necessary. Finally, run the code in Jupyter, the image will show up below the code on the web page. matplotlib works smoothly with Jupyter. If you are willing to open a browser to run the code and view the result, this is the best way I can think of.
  2. You can use the matplotlib headlessly. That means to remove all the code such as plt.show(). Use plt.savefig to save figures to filesystem instead of showing it in an opened window. Then you can check out these saved images using any image viewer.

I tried mounting X11 to docker images some time ago, like YW P Kwon's answer. It will only work on systems that use X11, and you can do this only on a local machine (I am not sure if X11 forward works). It is also not recommended in docker. While with the Jupyter and Headless solution, you can run your code on any platform. But you do need to modify your code a little bit.

like image 22
dailing Avatar answered Sep 20 '22 11:09

dailing