問題
エンタープライズWebアプリケーションの一部であるクライアントマシンのセットがあります。各マシンは、サーバーに接続するPyQTベースのWebクライアントである同一のソフトウェアを実行します。このクライアントソフトウェアは定期的に更新されます。各マシンで同じ環境を使用できるようにする構成/プロビジョニングツールがあり、クライアントの各マシンにソフトウェアを簡単に展開および構成できます。
問題は、私がChefを使用しようとしたことですが、実際にChefの知識とスキルを維持するには多大な労力が必要であり(専用のOps担当者はいません)、さらにサードパーティのリポジトリがあるとChefレシピが失敗する可能性があります もう利用できません (これは主要なストッパーです)。
この問題を解決するためにDockerを試してみたいと思いますが、GUIベースのソフトウェアが動作できるようにするイメージ/コンテナーをセットアップできる場合は、私は まだわかりません を使用します。
質問
Dockerを使用して、GUIベースのアプリケーション(PyQt/QT)の開発/運用環境を構築することは可能ですか?はいの場合、それにアプローチする最初のステップは何ですか?
現在、この質問には回答されていませんが、Googleで非常に高い評価を得ています。他の答えはほとんど正しいですが、難しい方法を学んだといういくつかの注意事項があり、他の人のトラブルを救いたいと思います。
Nasser Alshammariの答えは、Dockerコンテナー内でGTKアプリケーションを実行するための最も簡単な(そして最も速い)アプローチです-XサーバーのソケットをDockerボリュームとしてマウントし、代わりにDockerに使用するように指示します。
docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage
(X11アプリケーションをルートとして実行することは常に機能しないため、-u <username-within-container>
フラグを渡すことをお勧めします。通常はお勧めしません。セッションを共有する場合は特にをお勧めします)。
これは、xterm
などのアプリケーションとGTKベースのアプリケーションで機能します。たとえば、Firefox(GTKベース)でこれを試すと、動作します(ホストで既にFirefoxを実行している場合、Firefoxの新しいインスタンスを開くのではなく、ホストで新しいウィンドウを開くことに注意してください)コンテナ内から)。
しかし、あなたの答えはPyQTについて具体的に尋ねます。 Qtはこの方法でXセッションの共有をサポートしていないことがわかります (または少なくともそれをうまくサポートしていません)。
この方法でQTベースのアプリケーションを実行しようとすると、おそらく次のようなエラーが表示されます。
X Error: BadAccess (attempt to access private resource denied) 10
Extension: 140 (MIT-SHM)
Minor opcode: 1 (X_ShmAttach)
Resource id: 0x12d
X Error: BadShmSeg (invalid shared segment parameter) 148
Extension: 140 (MIT-SHM)
Minor opcode: 5 (X_ShmCreatePixmap)
Resource id: 0xb1
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 62 (X_CopyArea)
Resource id: 0x2c0000d
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Major opcode: 62 (X_CopyArea)
Resource id: 0x2c0000d
「おそらく」と言うのは、このアプローチを十分なQtアプリケーションでテストしていないか、Qtソースコードを掘り下げて、なぜこれがサポートされないのかを理解していないからです。 YMMV、そしてあなたは幸運になるかもしれませんが、Dockerコンテナ内からQtベースのアプリケーションを実行しようとしている場合、「昔ながらの」アプローチとeither
コンテナ内でsshdを実行し、X11転送をオンにしてから、ssh -X
(より安全)またはssh -Y
(安全性が低い、使用済みonlyを使用してコンテナに接続しますコンテナ化されたアプリケーション)。
コンテナ内でVNCを実行し、ホストからVNCクライアントで接続します。
これらの2つのオプションのうち、最初のオプションをお勧めしますが、どちらが最適かを確認してください。
DockerコンテナでGUIアプリを実行するには、多くのソリューションがあります。たとえば、SSHまたはVNCを使用できます。ただし、オーバーヘッドと遅延が追加されます。私が見つけた最良の方法は、ホストマシンのXサーバーが使用するファイルをボリュームとしてコンテナに渡すことです。このような:
docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage
その後、すべてのGUIアプリがコンテナーから実行されます。
お役に立てれば!
コンテナでxeyesを実行し、コンテナの外部で実行されているXサーバーの「ウィンドウ」を確認しました。方法は次のとおりです。
Xephyrを使用して、ネストされたXサーバーを実行しました。これは必須ではありませんが、ほとんどのLinuxデスクトップではデフォルトでリモートアプリの実行が許可されていません( here がubuntuでこれを「修正」する方法)。
Xephyrをインストールします。
$ Sudo apt-get install xserver-xephyr
Xephyrを実行します。
$ Xephyr -ac -br -noreset -screen 800x600 -Host-cursor :1
これにより、Xサーバーとして機能する新しい800x600ウィンドウが作成されます。
マシンの「外部」アドレスを見つけます。 Xサーバーが実行されている場所は次のとおりです。
$ ifconfig
docker0 Link encap:Ethernet HWaddr 56:84:7a:fe:97:99
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:133395 errors:0 dropped:0 overruns:0 frame:0
TX packets:242570 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:9566682 (9.5 MB) TX bytes:353001178 (353.0 MB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:650493 errors:0 dropped:0 overruns:0 frame:0
TX packets:650493 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2506560450 (2.5 GB) TX bytes:2506560450 (2.5 GB)
wlan0 Link encap:Ethernet HWaddr c4:85:08:97:b6:de
inet addr:192.168.129.159 Bcast:192.168.129.255 Mask:255.255.255.0
inet6 addr: fe80::c685:8ff:fe97:b6de/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6587370 errors:0 dropped:1 overruns:0 frame:0
TX packets:3716257 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:7405648745 (7.4 GB) TX bytes:693693327 (693.6 MB)
127.0.0.1は使用しないでください!他のどれでも使用できます。 172.17.42.1を使用します。
次のコンテンツでDockerfileを作成します。
FROM ubuntu
RUN apt-get update
RUN apt-get install -y x11-apps
CMD ["/usr/bin/xeyes"]
ビルドする:
$ docker build -t xeyes .
そしてそれを実行します:
$ docker run -e DISPLAY=172.17.42.1:1.0 xeyes
DISPLAY環境変数を表示したい場所に設定していることに注意してください。
同じ手法を使用して、表示を任意のXサーバーにリダイレクトできます。
最近、ドッカーでPyQt5アプリケーションを実行しようとしました。私が学んだことは、アプリケーションをルートとして実行できないことです(通常のユーザーを作成する必要があります)。アプリケーションでオーディオ/ビデオを再生するには、グループ「audio」でdocker containerを実行し、サウンドデバイスをマウントする必要があります。私のアプリケーションを実行するには、これを使用します:
docker run -it \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $(pwd)/test:/app \
-e DISPLAY=$DISPLAY \
-u myusername \
--group-add audio \
--device /dev/snd \
fadawar/docker-pyqt5-qml-qtmultimedia python3 /app/hello.py
コンテナーに追加してPyQtアプリケーションを実行する必要があるパッケージを特定するまでしばらく時間がかかるので、他のユーザーが簡単に使用できるように、いくつかのDockerfiles(簡単なデモアプリ)を作成しました。
Python 3 + PyQt5: https://github.com/jozo/docker-pyqt5
Python 3 + PyQt5 + QML + QtMultimedia: https://github.com/jozo/docker-pyqt5-qml-qtmultimedia
subuser を使用して、GUIアプリケーションをパッケージ化できます。また、アプリケーションの更新を適切にサポートしています。 Dockerfilesをgitリポジトリに1回入れてから、subuser update all
各クライアントで、変更が必要なときにイメージを再構築します。
順調に動作させるために必要な基本手順は次のとおりです。
Dockerコンテナーを作成して実行するには
Sudo nvidia-docker run -it -d --privileged -e DISPLAY=$DISPLAY --name wakemeeup -v -v /dev:/dev -v /tmp/.X11-unix:/tmp/.X11-unix:rw nvidia/cuda:9.1-cudnn7-devel-ubuntu16.04 bash
Dockerコンテナを開始するには
Sudo docker start wakemeup
Dockerコンテナに接続するには
xhost +local:root 1>/dev/null 2>&1 docker exec -u $USER -it wakemeup /bin/bash xhost -local:root 1>/dev/null 2>&1
MIT-SHMはXサーバーの拡張機能であり、共有メモリを使用することでトランザクションを高速化できます。 Docker分離はおそらくそれをブロックします。 Qtアプリケーションは、拡張機能を使用しないように強制できます。 Dockerコンテナ内で、
nano ~/.bashrc export QT_X11_NO_MITSHM=1
ソース.bashrc
source ~/.bashrc
これが役立つことを願っています
$ export QT_DEBUG_PLUGINS=1
_ ==>エラーを再現する==>デバッグメッセージにリストされている_No such file or directory
_- libraryを再インストールします==>繰り返します!また、エラーを受信せずにDockerコンテナーでPyQt5-GUI-appを実行することもできませんでした。まず、DockerコンテナーでQtを実行できないというすべての投稿を読みました。しかし、私はそれを解決できました(少なくとも私にとって)...
私はDockerコンテナ内のPyQt5-applicationを共有_/tmp/.X11-unix/
_ソケットとGUI視覚化のためのディスプレイで実行しています:
_$ nividia-docker run --interactive --tty --env DISPLAY=$DISPLAY --volume /tmp/.X11-unix/:/tmp/.X11-unix/ <docker_iamge>
_
_PyQt5.QtWidgets.QApplication
_を初期化すると、常に次のエラーが発生しました。
_Type "help", "copyright", "credits" or "license" for more information.
>>> from PyQt5.QtWidgets import QApplication
>>> app = QApplication([])
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
Aborted (core dumped)
_
PyCharmデバッグモードでは、エラーが返されました。
_Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
_
_ $ export QT_DEBUG_PLUGINS=1
_
_$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:22:34)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
KeyboardInterrupt
>>> from PyQt5.QtWidgets import QApplication, QLabel
>>> app = QApplication([])
_
_QFactoryLoader::QFactoryLoader() checking directory path "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms" ...
QFactoryLoader::QFactoryLoader() looking at "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqeglfs.so"
Found metadata in lib /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqeglfs.so, metadata=
{
"IID": "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.3",
"MetaData": {
"Keys": [
"eglfs"
]
},
...
...
...
Got keys from plugin meta data ("xcb")
QFactoryLoader::QFactoryLoader() checking directory path "/conda/envs/rapids/bin/platforms" ...
Cannot load library /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)
QLibraryPrivate::loadPlugin failed on "/conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so" : "Cannot load library /conda/envs/rapids/lib/python3.6/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
Aborted (core dumped)
_
<No such file or directory>.so.*
_および_<coud not be loaded>
_--パッケージを見つけます。 _libxkbcommon-x11.so.0
_およびlibxcb
。次に、対応するパッケージ/ライブラリを再/インストールします(パッケージの検索は_apt-file --package-only search <filename>
_または_conda/pip search ...
_で機能します)。私の場合、次のライブラリが必要でした:_### lib no.1 ###
$ Sudo conda install --name <env_name> --force-reinstall libxcb # or pip install ...
### lib no. 2 ###
$ apt-file --package-only search libxkbcommon-x11.so.0
libxkbcommon-x11-0
$ Sudo apt install libxkbcommon-x11-0
_
順次再生されるすべてのデバッグメッセージに対してこのプロセスを繰り返し、2つのライブラリをインストールした後、ローカルマシンのデスクトップのDockerコンテナー内からPyQt5-appsを実行できるようになりました。