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
-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
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
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?
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
--entry parameter, but it didn’t work. Please help.
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
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.
matplotlibworks 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.
matplotlibheadlessly. That means to remove all the code such as
plt.savefigto 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.
I tried in my own way and it works fine..
#To run "matplotlib" inside docker, you must install these inside containers:-#
yum install python3 -y //(must)
yum install python3-tkinter -y //(must)
pip3 install matplotlib // (must)
pip3 install pandas (if required)
pip3 install scikit-learn ( if required)
Now, run your container.
docker run --rm -it --env=DISPLAY --workdir=/app -v="$PWD:/app <image_name> python3 model.py
Bellow, I have described how to enable matplotlib plotting from running docker container and windows 10 machine.
Note, I didn’t have to change matplotlib backend using
matplotlib.use('TkAgg') as maybe others suggested in other posts.
For test I used simple python program:
# test.py import matplotlib.pyplot as plt plt.plot([1,2], [3,4]) plt.show()
The first thing is to add the following into the dockerfile, to install tkinter backend which matplotlib uses for graphical representation:
RUN apt-get update -y RUN apt-get install -y libx11-dev RUN apt-get install -y python3-tk
The second thing is to install vcXsrv server onto windows machine, which enables and establishes communication from running container to windows machine. Install and run it – you may follow instructions described on this page.
The last thing to do before building and running the docker image is to set
$DISPLAY variable in wsl terminal. I did this with:
, where IP is the network IP of windows machine.
In my case I ran:
After successfully executed steps above the image can be built.
Build it with:
docker build -t image_name .
Then run the container using command below where for display the before-set variable will be used.
docker run -ti --rm -e DISPLAY=$DISPLAY image_name
If everything was set correctly the matplotlib figure will pop-up.
It looks like
matplotlib is not meant to be used in
I noteice, when encounter thet problem, that
matplotlib was used for show and save figures.
Seaborn can save files and it works fine in
matplotlib and use
seaborn might be solution.