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.
As far as I know, there are two ways you can to this:
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.matplotlib
headlessly. That means to remove all the code such asplt.show()
. Useplt.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.
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: