Jesse Wei
Posted on December 6, 2022
Running a Python GUI app built with tkinter in Docker containers can be tricky. Tkinter cannot access the X11 socket, which it relies on to display graphical interfaces, of the Docker host from a Docker container without proper configuration. In this post, I want to share my hack for making my tkinter app work in Docker on a Mac machine.
Table of Contents
- Development Environment
- Step 1: Prepare Directories & Files
- Step 2: Add Some Code
- Step 3: Install & Configure XQuartz
- Step 4: Find Our IP Address
- Step 5: Build Image & Run Container
- Conclusion
Development Environment
- macOS Monterey 12.6
- docker 20.10.17
- docker-compose 1.29.2
Step 1: Prepare Directories & Files
Create a directory for our project and within it, create a Dockerfile
, a docker-compose.yml
file and a src/
directory. Your directory tree should look like this.
├── Dockerfile
├── docker-compose.yml
└── src
└── app.py
Step 2: Add Some Code
Copy & paste the following code into your Dockerfile
.
FROM python:3.10.7
WORKDIR /usr/src/app
COPY . .
CMD [ "python3", "./app.py" ]
Create an .env
file at the root of the project and add the following code to it.
SRC_PATH=./src
Then copy & paste the following code into your docker-compose.yml
file.
version: '3'
services:
python3:
build: .
container_name: 'python3'
stdin_open: true
working_dir: '/usr/src/app'
tty: true
volumes:
- ${SRC_PATH}:/usr/src/app
environment:
- DISPLAY=YOUR_IP_ADDRESS:0.0
Note: we have a DISPLAY
environment variable set to YOUR_IP_ADDRESS:0.0
for now, which we'll replace with our real ip address later.
Then, copy & paste the following code into your src/app.py
file.
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
Step 3: Install & Configure XQuartz
XQuartz is needed for our app to work in Docker on a Mac machine. So go to https://www.xquartz.org/, download and install it.
After installation, open Preferences > Security
and make sure both boxes are checked. Then restart XQuartz.
Step 4: Find Our IP Address
Remember in step 2, we had the DISPLAY
environment variable set to a placeholder. Now we need to replace it with our real ip address.
Open System Preferences > Network
. You can find your ip address here.
Replace the OUR_IP_ADDRESS
part in docker-compose.yml
with the ip address above. (e.g. if your ip address is 100.1.00.11
, the DISPLAY
environment variable value should be 100.1.00.11:0.0
).
Step 5: Build Image & Run Container
Before we can build our image and run our container, we need to run the following command in shell to disable X server's access control so that our app can access the host's X11 socket from within the container.
xhost +
Finally, let's build our image and run our container.
docker-compose up -d --build
The tkinter app window should pop up like the following.
Conclusion
When trying to run tkinter apps in Docker on a Mac, you may get various errors like _tkinter.TclError: no display name
and no $DISPLAY environment variable or _tkinter.TclError: couldn't connect to display ~
. These are due to incorrect configuration of the DISPLAY
environment variable or the X window system.
I found a lot of proposed solutions online but none of them worked for me. I tested multiple tricks and finally managed to get it work so if you were like me, this article may help you out.
Posted on December 6, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.