在 docker 容器中运行 pyautogui 脚本以控制主机屏幕

Run pyautogui script inside a docker container to control the host screen

提问人:The Nerdly Gentleman 提问时间:10/20/2023 更新时间:10/31/2023 访问量:116

问:

在工作中,我们使用 docker 容器在带有触摸屏显示器的定制 Linux 机器上运行我们的脚本。我是那里的 QA,我想创建一些自动化测试,这些测试应该执行虚拟触摸点击。

我的问题是,Linux 机器只有基本软件包,安装新软件包真的很棘手。另外,为了不弄乱操作系统本身,我也想在 docker 容器中使用我的自动化脚本。这也将使我有机会使用不同的软件包进行测试。

我想用它来模拟触摸屏上的输入(我知道这并不像听起来那么容易是有原因的)。目前,我坚持让 docker 容器访问屏幕。当我运行一个简单的测试脚本时,我收到以下两条错误消息pyautogui

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/Xlib/support/unix_connect.py", line 76, in get_socket
    s.connect('/tmp/.X11-unix/X%d' % dno)
ConnectionRefusedError: [Errno 111] Connection refused
Xlib.error.DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused

所以我知道问题出在 X11 的限制上。我正在尝试我在网上找到的不同解决方案,但没有一个有效。我的下一步是更多地了解它是如何工作的,但这可能需要一些时间。X11

也许你们中的一些人有解决方案或更好的方法来做到这一点。另外,如果我混淆了与这些主题相关的一些名称,我深表歉意。

我的样子是这样的:Dockerfile

FROM ubuntu:latest as notebook

WORKDIR /automation_test
COPY /src /automation_test/src

RUN apt update && apt-get update
RUN apt -y install python3 python3-pip
RUN pip install --upgrade pip
RUN pip install -r src/requirements.txt
RUN apt-get -y install -y wget
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN apt-get update && apt-get -y install google-chrome-stable
RUN apt-get -y install x11-apps
RUN apt-get -y install xauth
RUN apt-get -y install openbox
RUN mkdir /root/.Xauthority
RUN HOST=cctv
RUN DISPLAY_NUMBER=$(echo $DISPLAY | cut -d. -f1 | cut -d: -f2)
RUN AUTH_COOKIE=$(xauth list | grep "$(hostname)/unix:${DISPLAY_NUMBER} " | awk '{print $3}')
RUN xauth add ${HOST}/unix: ${DISPLAY_NUMBER} MIT-MAGIC-COOKIE-1 ${AUTH_COOKIE}
...

而我的是这样的:docker-compose.yaml

version: '3.6'

x-base: &base
    ipc: host
    pid: host
    privileged: true
    network_mode: host
    volumes:
      - ./src/results:/automation_test/src/results
      - ./src/tmp:/automation_test/src/tmp
      - /tmp/.X11-unix:/tmp/.X11-unix
    environment:
      - DISPLAY=${DISPLAY}
    extra_hosts:
      - "host.docker.internal:host-gateway"


services:

  notebook:
    <<: *base
    image: notebook
    container_name: notebook
    build: 
      context: .
      target: notebook
    command: ["/bin/bash"]

Disclaimer:这些文件中的大部分内容都是我尝试过的解决方案,但没有奏效。所以这就是它看起来有点丑陋和凌乱的原因。我目前使用的是 Ubuntu 基础映像。将来,我只想使用 python 图像作为基础。

蟒蛇 linux docker x11 pyautogui

评论

0赞 David Maze 10/20/2023
Docker 容器在设计上是一个隔离的环境,它通常根本无法与主机显示交互。Dockerfile 包含几个命令,用于尝试提取主机显示信息,但这些命令在 Dockerfile 中不起作用,因为命令也发生在容器内部。您需要的大多数设置都是在运行时进行的,而不是在映像构建时进行的;你能在 Linux Docker 容器中运行 GUI 应用程序吗? 有足够的详细信息吗?RUNRUN
0赞 tripleee 10/21/2023
控制主机的客人听起来像是......不寻常的安排。我敢肯定,如果您可以在虚拟机中运行要测试的系统的克隆,那么很多事情都会变得更容易。

答:

0赞 Philippe 10/21/2023 #1

你可以像这样做 x-forwarding:

#!/usr/bin/env bash

dir=$(mktemp -d); cd $dir

echo 'import pyautogui;pyautogui.write("Hello, World!")' > test.py 

docker build -t x-forwarding -f - . << EOF
FROM python
WORKDIR /app
COPY test.py ./
RUN pip install pyautogui python-xlib
EOF

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY\
    --name x-forwarding --rm x-forwarding python test.py

一旦这工作,你可以将其集成到你的docker-compose工作流程中。

评论

0赞 The Nerdly Gentleman 10/24/2023
我的解决方案得到了相同的结果。
0赞 Philippe 10/25/2023
您是否尝试过复制/粘贴我的命令?结果是什么?docker run ...
0赞 The Nerdly Gentleman 10/25/2023
是的,我把你的代码放进去,让文件运行。得出了同样的结果。init.sh
0赞 The Nerdly Gentleman 10/25/2023 #2

更新:

我必须纠正自己。我在这里提到的软件包也不是很有帮助。但是我发现了一个非常有趣的包,叫做python-evdev。我很惊讶我没有早点发现这个,也没有那么多网站提到它。理解起来有点多,因为文档有点粗糙,但对于我想做的事情来说,它就像一个魅力。

源语言:

所以我得出的结论是,我的这个项目太复杂了,暂时无法解决。我还注意到,它首先不起作用,因为我想运行存储库的 linux 机器甚至没有(可以首先诚实地检查一下)。X11

一位同事实际上给了我一个更好的方法来处理这个话题。他找到了这个直接与内核本身一起工作的存储库

我认为这是一个比尝试让 X11 在 docker 中运行更好的解决方案。

无论如何,感谢您的帮助和您的时间。我很感激。