在Docker运行Python GUI应用程序
#教程 #python #docker #gui

在Docker容器中运行使用tkinter构建的Python GUI应用程序可能很棘手。 TKINTER无法访问从docker容器中显示的X11套接字,它依赖于显示图形接口,而没有正确的配置。在这篇文章中,我想分享我的hack,以使我的tkinter应用程序在Mac机器上的Docker工作。

目录

发展环境

  • 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/,下载并安装。

XQuartz

安装后,打开Preferences > Security并确保检查两个盒子。然后重新启动Xquartz。

步骤4:找到我们的IP地址

记住在step 2中,我们将DISPLAY环境变量设置为占位符。现在我们需要用真实的IP地址替换它。

打开System Preferences > Network。您可以在这里找到您的IP地址。

find ip address

用上面的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应用程序窗口应像以下内容一样弹出。

tkinter window

结论

尝试在Mac上在Docker中运行TKINTER应用程序时,您可能会收到_tkinter.TclError: no display nameno $DISPLAY environment variable or _tkinter.TclError: couldn't connect to display ~等各种错误。这些是由于DISPLAY环境变量或X窗口系统的配置不​​正确。

我在网上找到了许多建议的解决方案,但它们都不适合我。我测试了多个技巧,并最终设法使它起作用,因此,如果您像我一样,本文可能会帮助您。