478

Linux Dockerコンテナーで GUI アプリケーションを実行するにはどうすればよいですか?

vncserverたとえば、Firefox の周りに追加のスピードバンプ サンドボックスを追加できるように設定するイメージなどはありますか?

4

24 に答える 24

211

Xauthority は、新しいシステムで問題になります。Docker コンテナーを実行する前に xhost + で保護を破棄するか、十分に準備された Xauthority ファイルを渡すことができます。一般的な Xauthority ファイルはホスト名固有です。docker を使用すると、コンテナーごとに異なるホスト名 (docker run -h で設定) を設定できますが、コンテナーのホスト名をホスト システムと同じに設定しても、私の場合は役に立ちませんでした。xeyes (私はこの例が好きです) は、単純にマジック Cookie を無視し、資格情報をサーバーに渡しません。したがって、「プロトコルが指定されていません。ディスプレイを開けません」というエラー メッセージが表示されます。

Xauthority ファイルは、ホスト名が問題にならないように記述できます。認証ファミリーを「FamilyWild」に設定する必要があります。xauth にこれに対する適切なコマンド ラインがあるかどうかはわかりません。そのため、xauth と sed を組み合わせてそれを行う例を次に示します。nlist 出力の最初の 16 ビットを変更する必要があります。FamilyWild の値は 65535 または 0xffff です。

docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes
于 2014-08-13T07:33:45.077 に答える
82

このブログ エントリを見つけたので、ここで共有したいと思います。これが最善の方法であり、とても簡単だと思うからです。

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

長所:
+ docker コンテナーに x サーバーの要素がない
+ vnc クライアント/サーバーが不要
+ x 転送による ssh が不要
+ はるかに小さい docker コンテナー

短所:
- ホストで x を使用する (安全なサンドボックス用ではありません)

いつかリンクが失敗する場合に備えて、最も重要な部分をここに置きました:
dockerfile:

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y firefox

# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
    mkdir -p /home/developer && \
    echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
    echo "developer:x:${uid}:" >> /etc/group && \
    echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
    chmod 0440 /etc/sudoers.d/developer && \
    chown ${uid}:${gid} -R /home/developer

USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox

イメージをビルドします。

docker build -t firefox .

そして実行コマンド:

docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox

もちろん、実行コマンドでこれを行うこともできますsh -c "echo script-here"

ヒント: オーディオについては、https ://stackoverflow.com/a/28985715/2835523 をご覧ください。

于 2015-03-10T18:28:44.453 に答える
58

docker データ ボリュームを使用すると、xorg の unix ドメイン ソケットをコンテナー内で簡単に公開できます。

たとえば、次のような Dockerfile を使用します。

FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes

次のことができます。

$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes

もちろん、これは本質的に X 転送と同じです。コンテナにホスト上の xserver へのフル アクセスを許可するため、中身が信頼できる場合にのみお勧めします。

注:セキュリティが心配な場合は、必須または役割ベースのアクセス制御でアプリを制限することをお勧めします。Docker はかなり優れた分離を実現しますが、別の目的を念頭に置いて設計されています。あなたの懸念に対処するために設計されたAppArmorSELinux、またはGrSecurityを使用してください。

于 2014-08-06T19:21:28.127 に答える
27

OSX

Jürgen Weigertは、Ubuntu でうまくいった最良の答えを持っていますが、OSX では、docker は VirtualBox 内で実行されるため、さらに作業を行わないとソリューションは機能しません。

これらの追加の成分で動作します:

  1. Xquartz (OSX は X11 サーバーに同梱されなくなりました)
  2. socat によるソケット転送 (brew install socat)
  3. コンテナを起動するbashスクリプト

OSX のこの回答を改善するためにユーザーのコメントをいただければ幸いです。X のソケット転送が安全かどうかはわかりませんが、Docker コンテナーをローカルでのみ実行することを目的としています。

また、ローカル ワイヤレス上にあり、常にランダムな IP であるため、マシンの IP アドレスを取得するのは簡単ではないという点で、スクリプトは少し脆弱です。

コンテナーの起動に使用する BASH スクリプト:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0

# Grab the ip address of this box
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}')

DISP_NUM=$(jot -r 1 100 200)  # random display number between 100 and 200

PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother

socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null &

XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$USER.$$
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/Users/$USER" \
    -v "/Users/$USER:/home/$USER:rw" \
    -v $XSOCK:$XSOCK:rw \
    -v $XAUTH:$XAUTH:rw \
    -e DISPLAY=$IPADDR:$DISP_NUM \
    -e XAUTHORITY=$XAUTH \
    $CONTAINER \
    $COMMAND

rm -f $XAUTH
kill %1       # kill the socat job launched above

このアプローチで xeyes と matplotlib を動作させることができます。

Windows 7+

MobaXterm を使用すると、Windows 7 以降で少し簡単になります。

  1. Windows 用の MobaXterm をインストールする
  2. MobaXterm を起動
  3. X サーバーの構成:設定-> X11 (タブ) -> X11 リモート アクセスフルに設定
  4. この BASH スクリプトを使用してコンテナーを起動します

run_docker.bash:

#!/usr/bin/env bash

CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)

docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/home/$USER" \
    -v "/c/Users/$USER:/home/$USER:rw" \
    -e DISPLAY \
    $CONTAINER \
    $COMMAND

PCで動くxeyes

于 2016-03-23T23:12:23.970 に答える
24

他の回答で述べられているように、ホスト ディスプレイ :0 の共有には 2 つの欠点があります。

  • X のセキュリティ リークが原因で、コンテナーの分離が中断されます。たとえば、xevまたはを使用したキーロギングや、 を使用したxinputホスト アプリケーションのリモート コントロールが可能ですxdotool
  • X 拡張 MIT-SHM の共有メモリが不足しているため、アプリケーションでレンダリングの不具合や RAM アクセスエラーが発生する可能性があります。(アイソレーション劣化オプションでも修正可能--ipc=host)。

以下は、この問題に対処する Xephyr で docker イメージを実行するスクリプトの例です。

  • Docker アプリケーションがネストされた X サーバーで実行されるため、X のセキュリティ リークが回避されます。
  • RAM アクセスの失敗を避けるため、MIT-SHM は無効になっています。
  • によってコンテナのセキュリティが向上し--cap-drop ALL --security-opt no-new-privilegesます。また、コンテナー ユーザーはrootではありません。
  • Xephyr ディスプレイへのアクセスを制限するために、X Cookie が作成されます。

スクリプトはいくつかの引数を想定しています。1 つ目は Xephyr で実行するホスト ウィンドウ マネージャー、2 つ目は Docker イメージ、3 つ目はオプションで実行するイメージ コマンドです。Docker でデスクトップ環境を実行するには、ホスト ウィンドウ マネージャーの代わりに「:」を使用します。

Xephyr ウィンドウを閉じると、docker コンテナー アプリケーションが終了します。ドッキングされたアプリケーションを終了すると、Xephyr ウィンドウが閉じます。

例:

  • xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
  • xephyrdocker : x11docker/lxde
  • xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom

xephyrdocker スクリプト:

#! /bin/bash
#
# Xephyrdocker:     Example script to run docker GUI applications in Xephyr.
#
# Usage:
#   Xephyrdocker WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]]
#
# WINDOWMANAGER     host window manager for use with single GUI applications.
#                   To run without window manager from host, use ":"
# DOCKERIMAGE       docker image containing GUI applications or a desktop
# IMAGECOMMAND      command to run in image
#
Windowmanager="$1" && shift
Dockerimage="$*"

# Container user
Useruid=$(id -u)
Usergid=$(id -g)
Username="$(id -un)"
[ "$Useruid" = "0" ] && Useruid=1000 && Usergid=1000 && Username="user$Useruid"

# Find free display number
for ((Newdisplaynumber=1 ; Newdisplaynumber <= 100 ; Newdisplaynumber++)) ; do
  [ -e /tmp/.X11-unix/X$Newdisplaynumber ] || break
done
Newxsocket=/tmp/.X11-unix/X$Newdisplaynumber

# cache folder and files
Cachefolder=/tmp/Xephyrdocker_X$Newdisplaynumber
[ -e "$Cachefolder" ] && rm -R "$Cachefolder"
mkdir -p $Cachefolder
Xclientcookie=$Cachefolder/Xcookie.client
Xservercookie=$Cachefolder/Xcookie.server
Xinitrc=$Cachefolder/xinitrc
Etcpasswd=$Cachefolder/passwd

# command to run docker
# --rm                               created container will be discarded.
# -e DISPLAY=$Newdisplay             set environment variable to new display
# -e XAUTHORITY=/Xcookie             set environment variable XAUTHORITY to provided cookie
# -v $Xclientcookie:/Xcookie:ro      provide cookie file to container
# -v $NewXsocket:$NewXsocket:ro      Share new X socket of Xephyr
# --user $Useruid:$Usergid           Security: avoid root in container
# -v $Etcpasswd:/etc/passwd:ro       /etc/passwd file with user entry
# --group-add audio                  Allow access to /dev/snd if shared with '--device /dev/snd' 
# --cap-drop ALL                     Security: disable needless capabilities
# --security-opt no-new-privileges   Security: forbid new privileges
Dockercommand="docker run --rm \
  -e DISPLAY=:$Newdisplaynumber \
  -e XAUTHORITY=/Xcookie \
  -v $Xclientcookie:/Xcookie:ro \
  -v $Newxsocket:$Newxsocket:rw \
  --user $Useruid:$Usergid \
  -v $Etcpasswd:/etc/passwd:ro \
  --group-add audio \
  --env HOME=/tmp \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  $(command -v docker-init >/dev/null && echo --init) \
  $Dockerimage"

echo "docker command: 
$Dockercommand
"

# command to run Xorg or Xephyr
# /usr/bin/Xephyr                an absolute path to X server executable must be given for xinit
# :$Newdisplaynumber             first argument has to be new display
# -auth $Xservercookie           path to cookie file for X server. Must be different from cookie file of client, not sure why
# -extension MIT-SHM             disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it)
# -nolisten tcp                  disable tcp connections for security reasons
# -retro                         nice retro look
Xcommand="/usr/bin/Xephyr :$Newdisplaynumber \
  -auth $Xservercookie \
  -extension MIT-SHM \
  -nolisten tcp \
  -screen 1000x750x24 \
  -retro"

echo "X server command:
$Xcommand
"

# create /etc/passwd with unprivileged user
echo "root:x:0:0:root:/root:/bin/sh" >$Etcpasswd
echo "$Username:x:$Useruid:$Usergid:$Username,,,:/tmp:/bin/sh" >> $Etcpasswd

# create xinitrc
{ echo "#! /bin/bash"

  echo "# set environment variables to new display and new cookie"
  echo "export DISPLAY=:$Newdisplaynumber"
  echo "export XAUTHORITY=$Xclientcookie"

  echo "# same keyboard layout as on host"
  echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - :$Newdisplaynumber"

  echo "# create new XAUTHORITY cookie file" 
  echo ":> $Xclientcookie"
  echo "xauth add :$Newdisplaynumber . $(mcookie)"
  echo "# create prepared cookie with localhost identification disabled by ffff,"
  echo "# needed if X socket is shared instead connecting over tcp. ffff means 'familiy wild'"
  echo 'Cookie=$(xauth nlist '":$Newdisplaynumber | sed -e 's/^..../ffff/')" 
  echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -'
  echo "cp $Xclientcookie $Xservercookie"
  echo "chmod 644 $Xclientcookie"

  echo "# run window manager in Xephyr"
  echo $Windowmanager' & Windowmanagerpid=$!'

  echo "# show docker log"
  echo 'tail --retry -n +1 -F '$Dockerlogfile' 2>/dev/null & Tailpid=$!'

  echo "# run docker"
  echo "$Dockercommand"
} > $Xinitrc

xinit  $Xinitrc -- $Xcommand
rm -Rf $Cachefolder

このスクリプトはx11docker wikiで管理されています。より高度なスクリプトは、GPU アクセラレーション、Web カメラ、プリンター共有などの機能もサポートするx11dockerです。

于 2016-09-24T21:13:22.173 に答える
19

Xこれは、コンテナーにサーバー、vncサーバー、またはsshdデーモンをインストールする必要がない軽量のソリューションです。シンプルさで得られるものは、セキュリティと分離で失われます。

転送を使用sshしてホスト マシンに接続することを前提としています。X11

ホストのsshd構成で、次の行を追加します

X11UseLocalhost no

ホスト上の転送された X サーバー ポートがすべてのインターフェース ( だけでなくlo) で、特に Docker 仮想インターフェース で開かれるようにしますdocker0

コンテナーは、実行時.Xauthorityに、サーバーに接続できるようにファイルにアクセスする必要があります。そのために、ホストのホーム ディレクトリを指す読み取り専用ボリュームを定義し (賢明な考えではないかもしれません!)、XAUTHORITYそれに応じて変数を設定します。

docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority

それだけでは十分ではありません。ホストから DISPLAY 変数を渡す必要もありますが、ホスト名を IP に置き換えます。

-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")

エイリアスを定義できます。

 alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'

そして、次のようにテストします。

dockerX11run centos xeyes
于 2014-06-30T19:51:13.063 に答える
7

GUI アプリケーションをヘッドレスで実行したい場合は、こちらをお読みください。あなたがしなければならないことは、xvfbまたは他の同様のソフトウェアで仮想モニターを作成することです. これは、たとえばブラウザーで Selenium テストを実行する場合に非常に役立ちます。

どこにも言及されていないことは、一部のソフトウェア自体が実際に Linux コンテナーでサンドボックス化を使用しているということです。たとえば--privileged、コンテナを実行するときに適切なフラグを使用しないと、Chrome は正常に実行されません。

于 2014-10-18T09:23:06.847 に答える
6

VNC、SSH、および X11 転送を使用せずにコンテナで GUI アプリを実行する lord.garbage による別のソリューションがあります。ここでも言及されています。

于 2014-09-23T13:59:06.733 に答える
4

次の手順に従ってopencv、USB カメラからビデオ ストリームを実行することができました。docker

  1. docker が X サーバーにアクセスできるようにする

    xhost +local:docker
    
  2. X11 Unix ソケットと X 認証ファイルを作成する

    XSOCK=/tmp/.X11-unix
    XAUTH=/tmp/.docker.xauth
    
  3. 適切な権限を追加する

    xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
    
  4. X11 レンダリング エンジンをバイパスしないように、Qt レンダリング速度を「ネイティブ」に設定します。

    export QT_GRAPHICSSYSTEM=native
    
  5. Qt に MIT-SHM (共有メモリ) を使用しないように指示する - そうすれば、セキュリティ的にも安全になります。

    export QT_X11_NO_MITSHM=1
    
  6. docker run コマンドを更新する

    docker run -it \
               -e DISPLAY=$DISPLAY \
               -e XAUTHORITY=$XAUTH \
               -v $XSOCK:$XSOCK \
               -v $XAUTH:$XAUTH \
               --runtime=nvidia \
               --device=/dev/video0:/dev/video0 \
               nvcr.io/nvidia/pytorch:19.10-py3
    

注: プロジェクトを終了したら、アクセス制御をデフォルト値に戻します -xhost -local:docker

詳細: Docker での GUI の使用

クレジット: Tensorflow、OpenCV、および Docker を使用したリアルタイムおよびビデオ処理オブジェクトの検出

于 2019-10-31T15:58:18.563 に答える
3

Docker ユーザー (ここでは root) に X11 ディスプレイへのアクセスを許可できます。

XSOCK=/tmp/.X11-unix
xhost +SI:localuser:root 
docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image 
xhost -SI:localuser:root
于 2016-08-11T10:00:57.187 に答える