在Docker容器中运行使用tkinter构建的Python GUI应用程序可能很棘手。 TKINTER无法访问从docker容器中显示的X11套接字,它依赖于显示图形接口,而没有正确的配置。在这篇文章中,我想分享我的hack,以使我的tkinter应用程序在Mac机器上的Docker工作。
目录
- 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
发展环境
- Macos Monterey 12.6
- Docker 20.10.17
- Docker-Compose 1.29.2
步骤1:准备目录和文件
为我们的项目创建一个目录,并在其中创建一个Dockerfile
,一个docker-compose.yml
文件和一个src/
目录。您的目录树应该看起来像这样。
├── Dockerfile
├── docker-compose.yml
└── src
└── app.py
步骤2:添加一些代码
将以下代码复制到您的Dockerfile
中。
FROM python:3.10.7
WORKDIR /usr/src/app
COPY . .
CMD [ "python3", "./app.py" ]
在项目的根部创建一个.env
文件并向其添加以下代码。
SRC_PATH=./src
然后将以下代码复制到您的docker-compose.yml
文件中。
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
注意:我们现在有一个DISPLAY
环境变量设置为YOUR_IP_ADDRESS:0.0
,我们将稍后用真实的IP地址替换。
然后,将以下代码复制到您的src/app.py
文件中。
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()
步骤3:安装和配置Xquartz
XQuartz是我们的应用程序在Mac机器上在Docker上工作的。因此,请访问https://www.xquartz.org/,下载并安装。
安装后,打开Preferences > Security
并确保检查两个盒子。然后重新启动Xquartz。
步骤4:找到我们的IP地址
记住在step 2中,我们将DISPLAY
环境变量设置为占位符。现在我们需要用真实的IP地址替换它。
打开System Preferences > Network
。您可以在这里找到您的IP地址。
用上面的IP地址替换OUR_IP_ADDRESS
零件。 (例如,如果您的IP地址为100.1.00.11
,则DISPLAY
环境变量值应为100.1.00.11:0.0
)。
步骤5:构建图像和运行容器
在我们可以构建图像并运行容器之前,我们需要在Shell中运行以下命令以禁用X Server的访问控件,以便我们的应用程序可以从容器内部访问主机的X11套接字。
xhost +
最后,让我们构建图像并运行我们的容器。
docker-compose up -d --build
tkinter应用程序窗口应像以下内容一样弹出。
结论
尝试在Mac上在Docker中运行TKINTER应用程序时,您可能会收到_tkinter.TclError: no display name
和no $DISPLAY environment variable or _tkinter.TclError: couldn't connect to display ~
等各种错误。这些是由于DISPLAY
环境变量或X窗口系统的配置不正确。
我在网上找到了许多建议的解决方案,但它们都不适合我。我测试了多个技巧,并最终设法使它起作用,因此,如果您像我一样,本文可能会帮助您。