DockerコンテナーでGUIアプリケーションを実行できますか?


409

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

vncserverたとえば、Firefoxと言って周りにスピードバンプサンドボックスを追加できるように設定した画像はありますか?


この質問はLinux(年齢と回答の内容に基づく)にのみ関係し、Windowsには関係しないようです。もしそうなら、これを明確にするためにタイトルを編集できますか?ありがとう
UuDdLrLrSs


HPC Visualization Containersユーザーガイドでいくつかのアイデアを確認してください。
ケノーブ

回答:


238

あなたは単にFirefoxと共にvncserverをインストールすることができます:)

ここに画像、vnc / firefoxをプッシュしました: docker pull creack/firefox-vnc

イメージはこのDockerfileで作成されています。

# Firefox over VNC
#
# VERSION               0.1
# DOCKER-VERSION        0.2

FROM    ubuntu:12.04
# Make sure the package repository is up to date
RUN     echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN     apt-get update

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN     apt-get install -y x11vnc xvfb firefox
RUN     mkdir ~/.vnc
# Setup a password
RUN     x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way to do it, but it does the trick)
RUN     bash -c 'echo "firefox" >> /.bashrc'

これにより、パスワードを使用してVNCを実行するDockerコンテナが作成されます1234

Dockerバージョン18以降の場合:

docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create

Dockerバージョン1.3以降の場合:

docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create

バージョン1.3より前のDockerの場合:

docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create

2
VNCクライアントを使用してこれをリモートで表示するにはどうすればよいですか?IP +ポートの入力が機能していないようです。
user94154 2013

17
まず、あなたが実行して(割り当てられたポートを確認する必要がありますdocker inspect <container id>または単にdocker psあなただけ見つけ、その後、あなたがポートを使用して、ホストのIPに接続します。
creack

9
creackfirefox-vncイメージが次のエラーで失敗する:Enter VNC password:stty:standard input:Inappropriate ioctl for device fgets:No such file or directory stty:Standard input:Inappropriate ioctl for device x11vnc -usepw:could not find a password ..
alfonsodev 2014

6
Dockerをうまく使う> DockerでGUIアプリを実行する fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker
Dennis C

7
ユーザー名はありません。パスワードは回答に明確に示され、vncクライアントはそれを行います。私の場合、ネイティブのosxが好きです。(ファインダーからcommand + Kを押してvnc:// <docker ip>:<container exposed port>に接続します)
2014年

195

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

8
ただのメモ、-v $XSOCK:$XSOCK -v $XAUTH:$XAUTH短くすることができます-v $XSOCK -v $XAUTH
Piotr Aleksander Chmielowski

2
@PiotrAleksanderChmielowski(私にはうまくいきませんでした、Dockerバージョン1.12.0、ビルド8eab29e
tbc0

14
@Dirk:に置き換えたい場合が:0あり$DISPLAYます。それは意味xauth nlist $DISPLAY | ...docker run -ti -e DISPLAY=$DISPLAY ...ます。通常、X DISPLAYはですが:0、常にではありません(特にssh -Xで接続している場合はそうではありません)。
johndodo 16

4
Ubuntu 16.04では、xauthは権限を/tmp/.docker.xauth持つファイルを作成します600。これにより、dockerコンテナー内のxauthがファイルを読み取ることができなくなります。xauth listDockerコンテナー内で実行することで確認できます。これを解決するためにコマンドのchmod 755 $XAUTH後に追加しましたxauth nlist :0 | ...
アバイ2017

2
@Abai 444または644で十分なのに、なぜ755を使用するのですか?
Daniel Alder

68

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

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

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

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


Windows 7でこれを行うにはどうすればよいですか?Xサーバーをインストールする必要がありますか?
walksignison

3
ここでのほとんどの回答として、これはUNIXにのみ当てはまると思います-WindowsがXサーバーウィンドウシステムをサポートするまでは。
A. Binzxxxxxx

XサーバーをWindowsにインストールしたり、XサーバーをDockerコンテナーにバンドルしたりしても、うまくいくと思いますか?
walksignison、2018年

1
フォルダapt-get -y install sudoを作成するには、Dockerfile にもインストールする必要があると思い/etc/sudoers.dます。
mulg0r

1
また、と任意のホストからXへ接続できるようにする必要があるかもしれない$ xhost +
Bandoos

52

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を使用してください。これらは懸念事項に対処するように設計されています。


5
また、xhostなどのツールを使用して、他のホストからXサーバーへのアクセスを許可する必要があります。それを完全に開くxhost +には、ホストで使用します。
Tully

3
@Tullyのみxhost +localが必要です。作るために良いだろう~/.Xauthority、それは自身を認証することができますので、しかし、容器内のファイルが利用可能。
Aryeh Leib Taurog 2014年

3
Macで(boot2dockerを使用して)正常に動作しましたか?
Karl Forner 14年

4
これは、Docker 1.5以前のUbuntu 14.04ラップトップで私にとってはかなりうまく機能していました。しかし、Ubuntu 15.04、docker 1.6.2でエラーが発生して失敗しましたCan't open display: :0。何か案は?
cboettig 2015年

6
xhost +si:localuser:$USERコンテナーを起動するユーザーのみを承認するために使用しました。
Nick Breen

26

サブユーザーを使用することもできます:https : //github.com/timthelion/subuser

これにより、多くのGUIアプリをdockerにパッケージ化できます。Firefoxとemacsはこれまでにテストされています。ただし、FirefoxではwebGLは機能しません。Chromiumはまったく機能しません。

編集:サウンドは機能します!

EDIT2:私が最初にこれを投稿して以来、サブユーザーは大きく進歩しました。私は今、webuser up subuser.orgと、XPRAブリッジ経由で X11に接続するための新しいセキュリティモデルを持っています。


3
サブユーザーはまだ非常に新しく、比較的テストされていないことに注意してください。問題が発生した場合は、バグレポートを送信してください。
timthelion 2014

あなたができる方法があるなら、私はX11を避けます。キラーアプリは、DockerでTorプロキシを実行し、ファイアウォールなどがTor Dockerを介してすべてのネットワークを強制するように、フルブラウザーでプラグインを子Dockerで実行します。これは、リッチコンテンツを通過させるため、Webの使いやすさのために現在のTorブラウザーバンドルを周回します。
ウィル

1
X11のセキュリティに問題はありますか?それとも、これをウィンドウで操作したいですか?または、これをリモートで機能させたいですか?上記のすべて?これをvncで動作させることは非常に可能だと思います(ただし、vncへの依存関係を追加するため、これをデフォルトの方法にしないことにします)。サブユーザーをリモートで機能させることは、実際には不可能/意味がない。これもあります:github.com/rogaha/docker-desktopですが、バグレポートから、xpraは実際には使用できない可能性があります。
timthelion 2014

24

OSX

JürgenWeigertが私にとって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以降

Windows 7以降ではMobaXtermを使用する方が少し簡単です。

  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


bashスクリプトの意味を理解できませんでした-Windowsで実行するにはどうすればよいですか?
販売店

@deller GITを使用してWindowsでソフトウェア開発を行っているので、GIT-bashシェルを利用できます。
Nick

私は手順に従いました。しかし、私は取得error: XDG_RUNTIME_DIR not set in the environment.してError: cannot open display: VAIO:0.0。このような何かに遭遇しましたか?
user3275​​095 2017年

1
ユーザーが見つからない、つまり「passwdファイルに一致するエントリがない」というエラーが表示されます。
walksignison、2018年

19

他のいくつかの回答で述べたように、ホストディスプレイ:0を共有すると、2つの欠点があります。

  • いくつかのXセキュリティリークが原因で、コンテナーの分離が解除されます。たとえば、xevまたはによるキーロギングxinput、およびによるホストアプリケーションのリモート制御が可能ですxdotool
  • X拡張MIT-SHMの共有メモリがないために、アプリケーションでレンダリングの不具合や不良RAMアクセスエラーが発生する可能性があります。(絶縁劣化オプションで修正することもできます--ipc=host)。

この問題に対処するXephyrでDockerイメージを実行するスクリプトの例を以下に示します。

  • 入れ子になったXサーバーでdockerアプリケーションが実行されるため、Xセキュリティリークが回避されます。
  • RAMアクセス障害を回避するために、MIT-SHMは無効になっています。
  • コンテナのセキュリティはで改善されてい--cap-drop ALL --security-opt no-new-privilegesます。また、コンテナーユーザーはrootではありません
  • X cookieは、Xephyrディスプレイへのアクセスを制限するために作成されます。

スクリプトはいくつかの引数を想定しています。最初にホストウィンドウマネージャーをXephyrで実行し、2番目にdocker image、3番目にオプションでimageコマンドを実行します。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で管理されています。より高度なスクリプトはx11dockerで、GPUアクセラレーション、ウェブカメラ、プリンター共有などの機能もサポートしています。


18

これは、コンテナーに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

2
(これは、信頼できるアプリケーションのための素晴らしいですが、しかし、あなたはX-転送を避けたいサンドボックスのいずれかの種類について。。)
ウィル

1
ホームディレクトリ全体をコンテナにマウントしない場合は、.Xauthorityファイル自体をマウントできます-v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
Robert Haines、2015

2
を変更する代わりに、コマンドのX11UseLocalhost追加オプション--net=hostを使用することもできますdocker runここにあります)。
ingomueller.net 2017

--net=host...今、あなたは、コンテナ内のポートを開くかのように、それは同様にホストにオープンになります悪い考えです
MRR

16

JürgenWeigertの答えは基本的にこのソリューションをカバーしていますが、そこで何が説明されているのか最初はわかりませんでした。他の誰かが説明を必要とする場合に備えて、私の見解を追加します。

まず、関連ドキュメントはXセキュリティマンページです。

多数のオンラインソースが、X11 UNIXソケットと~/.Xauthorityファイルをコンテナにマウントすることを提案しています。これらのソリューションは多くの場合、理由を本当に理解せずに運が良ければ機能します。たとえば、コンテナーユーザーはユーザーと同じUIDで終了するため、マジックキー認証の必要はありません。

まず、Xauthorityファイルにはモード0600があるため、同じUIDを持たない限り、コンテナーユーザーはファイルを読み取ることができません。

ファイルをコンテナにコピーして所有権を変更しても、さらに別の問題があります。xauth list同じXauthorityファイルを使用してホストとコンテナで実行すると、異なるエントリが表示されます。これは、xauth実行場所に応じてエントリをフィルタリングするためです。

コンテナ内のXクライアント(つまり、GUIアプリ)はと同じように動作しxauthます。つまり、ユーザーのデスクトップで実行されているXセッションのマジックCookieは表示されません。代わりに、以前に開いたすべての「リモート」Xセッション(以下で説明)のエントリが表示されます。

したがって、必要なのは、コンテナのホスト名とホストCookieと同じ16進キー(つまり、デスクトップで実行されているXセッション)で新しいエントリを追加することです。例:

containerhostname/unix:0   MIT-MAGIC-COOKIE-1   <shared hex key>

問題はxauth add、コンテナ内でCookieを追加する必要があることです。

touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>

それ以外の場合はxauth、コンテナの外でのみ見えるようにタグ付けします。

このコマンドの形式は次のとおりです。

xauth add hostname/$DISPLAY protocol hexkey

どこ.表しMIT-MAGIC-COOKIE-1プロトコルを。

注:.Xauthorityコンテナーにコピーまたはバインドマウントする必要はありません。次のように空のファイルを作成し、Cookieを追加するだけです。

JürgenWeigertの答えは、FamilyWild接続タイプを使用してホスト上に新しい認証ファイルを作成し、それをコンテナーにコピーすることで、これを回避します。それは最初から現在のXセッションの六角キーを抽出ことに注意してください~/.Xauthority使用をxauth nlist

したがって、重要な手順は次のとおりです。

  • ユーザーの現在のXセッションのCookieの16進キーを抽出します。
  • コンテナーのホスト名と共有16進キーを使用して、コンテナーに新しいXauthorityファイルを作成します(またはFamilyWild接続タイプを使用してCookieを作成します)。

どのように機能するのかFamilyWildxauthまたはXクライアントが実行場所に応じてXauthorityファイルからエントリーをフィルターする方法がよくわかりません。これに関する追加情報は大歓迎です。

Dockerアプリを配布する場合は、コンテナーを実行するための開始スクリプトが必要です。このスクリプトは、ユーザーのXセッションの16進キーを取得し、前述の2つの方法のいずれかでコンテナーにインポートします。

また、承認プロセスの仕組みを理解するのにも役立ちます。

  • コンテナで実行されているXクライアント(つまりGUIアプリケーション)は、コンテナのホスト名との値に一致するCookieエントリをXauthorityファイルで探します$DISPLAY
  • 一致するエントリが見つかった場合、Xクライアント/tmp/.X11-unixは、コンテナにマウントされたディレクトリ内の適切なソケットを介して、認証リクエストとともにXサーバーにエントリを渡します。

注: X11 Unixソケットは引き続きコンテナーにマウントする必要があります。そうしないと、コンテナーはXサーバーへのルートを持ちません。セキュリティ上の理由から、ほとんどのディストリビューションでは、デフォルトでXサーバーへのTCPアクセスが無効になっています。

追加情報について、およびXクライアント/サーバーの関係がどのように機能するかをよりよく理解するために、SSH X転送の例のケースを調べることも役立ちます。

  • リモートマシンで実行されているSSHサーバーは、独自のXサーバーをエミュレートします。
  • それは$DISPLAY自身のXサーバーを指すようにSSHセッションの値を設定します。
  • xauthリモートホストの新しいCookieを作成するために使用しXauthority、ローカルユーザーとリモートユーザーの両方のファイルにそれを追加します。
  • GUIアプリが起動すると、SSHのエミュレートされたXサーバーと通信します。
  • SSHサーバーは、このデータをローカルデスクトップのSSHクライアントに転送します。
  • ローカルのSSHクライアントは、SSHクライアントが実際にXクライアント(つまりGUIアプリ)であるかのように、デスクトップで実行されているXサーバーセッションにデータを送信します。
  • Xサーバーは受け取ったデータを使用して、デスクトップにGUIをレンダリングします。
  • この交換の開始時に、リモートXクライアントは、作成されたばかりのCookieを使用して、承認リクエストも送信します。ローカルXサーバーはそれをローカルコピーと比較します。

12

これは軽量ではありませんが、完全なデスクトップ仮想化と同等のDocker機能を提供する優れたソリューションです。UbuntuとCentOSのXfce4とIceWMの両方が機能し、このnoVNCオプションにより、ブラウザーから簡単にアクセスできます。

https://github.com/ConSol/docker-headless-vnc-container

のvncserver noVNCと同様に実行されますtigerVNC。次にstartx、指定されたウィンドウマネージャーを呼び出します。さらにlibnss_wrapper.so、ユーザーのパスワード管理をエミュレートするために使用されます。


誰かこれをテストしましたか?
guilhermecgs 2017年

3
@guilhermecgsはい、正常に動作します。それ以来、xpraルートレスXであるdocker も試しました。これxpraは、最も適したIMOであり、VNCよりも効率的です。
ダッシュ

明確にするために...この画像で完全なデスクトップエクスペリエンス(GNOME、KDE)を利用できますか?
guilhermecgs 2017年

私はXfce4とIceWM(そのリポジトリにあります)だけを試しました。もちろん、エクスペリエンスは制限されます。たとえば、Dockerに渡し--device /dev/...て必要な--cap権限を設定しない限り、マウントデバイスはデスクトップ(gvfs)に表示されません。これは封じ込めの目的に反しますが、デバイスを通過できます。多少の調整を行うことで、GNOME / KDEをVNCの下で実行できると信じています。私はnvidiaカード(VNCまたはXpraなし)を備えたdockerで複数のXを実行したので、それは確かに実行可能です。
17:39の17:06の

今のところ試していません。これに関する最大の課題は、動作しているD-Busデーモンを起動することです。ほとんどのgnomeまたはKDEデスクトップはそれらを必要とします。月Ubuntuのデスクトップ-LXDE-VNCのプロジェクトがあなたを助けます。
toschneck 2018

11

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/にあるソリューションは、コンテナ内からGUIアプリケーションを開始する簡単な方法のようです(私はfirefoxを試してみましたubuntu 14.04以上)ですが、著者が投稿したソリューションに少し追加の変更が必要であることがわかりました。

具体的には、コンテナを実行するために、作成者は次のように述べています。

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

しかし、(同じサイトの特定のコメントに基づいて)2つの追加オプションがあることがわかりました

    -v $HOME/.Xauthority:$HOME/.Xauthority

そして

    -net=host 

コンテナを実行している間、Firefoxが正しく機能するように指定する必要があります。

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

そのページの情報とこれらの追加の調査結果を含むDockerイメージを作成しました:https : //hub.docker.com/r/amanral/ubuntu-firefox/


3
私はあなたが/tmp/.X11-unixソケットを渡すことさえまったく嫌がっていることを発見しました。それはマウント.Xauthorityとで動作し--net=hostます。
CMCDragonkai 2018

2
これは実際に最近機能する唯一のソリューションです。/tmp/.X11-unixdockerがスティッキディレクトリからのボリュームマウントを黙って拒否するため、as volume を使用しても機能しなくなりました。
クリスチャンHujer

1
使用しているディストリビューションによって異なると思います。CentOSでX11 Unixソケットをバインドマウントすることは間違いありません。何をするかを理解することも重要--network=hostです。これにより、コンテナがホストのネットワークスタックに完全にアクセスできるようになります。これは、何をしようとしているかによっては望ましくない場合があります。デスクトップでコンテナー化されたGUIをいじくり回しているだけであれば、問題はありません。
orodbhen


7

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

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


6

私は遅れて相手にだけど、XQuartzの道を行きたくないMacユーザーのために、ここではデスクトップ環境(XFCE)を使用して、Fedoraのイメージを構築する実施例であるXvfbVNC。シンプルで機能します。

Macでは、画面共有(デフォルト)アプリケーションを使用して、に接続するだけでアクセスできますlocalhost:5901

Dockerfile:

FROM fedora

USER root

# Set root password, so I know it for the future
RUN echo "root:password123" | chpasswd

# Install Java, Open SSL, etc.
RUN dnf update -y --setopt=deltarpm=false  \
 && dnf install -y --setopt=deltarpm=false \
                openssl.x86_64             \
                java-1.8.0-openjdk.x86_64  \
                xorg-x11-server-Xvfb       \
                x11vnc                     \
                firefox                    \
                @xfce-desktop-environment  \
 && dnf clean all

# Create developer user (password: password123, uid: 11111)
RUN useradd -u 11111 -g users -d /home/developer -s /bin/bash -p $(echo password123 | openssl passwd -1 -stdin) developer

# Copy startup script over to the developer home
COPY start-vnc.sh /home/developer/start-vnc.sh
RUN chmod 700 /home/developer/start-vnc.sh
RUN chown developer.users /home/developer/start-vnc.sh

# Expose VNC, SSH
EXPOSE 5901 22

# Set up VNC Password and DisplayEnvVar to point to Display1Screen0
USER developer
ENV  DISPLAY :1.0
RUN  mkdir ~/.x11vnc
RUN  x11vnc -storepasswd letmein ~/.x11vnc/passwd

WORKDIR /home/developer
CMD ["/home/developer/start-vnc.sh"]

start-vnc.sh

#!/bin/sh

Xvfb :1 -screen 0 1024x768x24 &
sleep 5
x11vnc -noxdamage -many -display :1 -rfbport 5901 -rfbauth ~/.x11vnc/passwd -bg
sleep 2
xfce4-session &

bash
# while true; do sleep 1000; done

必要に応じて、リンクされたreadmeでビルドコマンドと実行コマンドを確認してください。


5

ユルゲン・ワイガートの答えに基づいて、私はいくつかの改善をしています:

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_DIR=/tmp/.docker.xauth
XAUTH=$XAUTH_DIR/.xauth
mkdir -p $XAUTH_DIR && touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH_DIR:$XAUTH_DIR -e XAUTHORITY=$XAUTH xeyes

唯一の違いは、$ XAUTHファイルを配置し、$ XAUTHファイルの代わりに$ XAUTH_DIRディレクトリをdockerコンテナーにマウントするために使用されるディレクトリ$ XAUTH_DIRを作成することです。

この方法の利点は、/ etc / rc.localにコマンドを記述して、/ tmpに$ XAUTH_DIRという名前の空のフォルダーを作成し、そのモードを777に変更できることです。

tr '\n' '\000' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|\x00XAUTH_DIR=.*\x00\x00|\x00|' /etc/rc.local >/dev/null
tr '\000' '\n' < /etc/rc.local | sudo tee /etc/rc.local >/dev/null
sudo sed -i 's|^exit 0.*$|XAUTH_DIR=/tmp/.docker.xauth; rm -rf $XAUTH_DIR; install -m 777 -d $XAUTH_DIR\n\nexit 0|' /etc/rc.local

システムの再起動時、ユーザーのログイン前に、コンテナーの再起動ポリシーが「常に」の場合、Dockerは$ XAUTH_DIRディレクトリを自動的にマウントします。ユーザーのログイン後、$ XAUTHファイルを作成するコマンドを〜/ .profileに書き込むと、コンテナーはこの$ XAUTHファイルを自動的に使用します。

tr '\n' '\000' < ~/.profile | sudo tee ~/.profile >/dev/null
sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile
tr '\000' '\n' < ~/.profile | sudo tee ~/.profile >/dev/null
echo "XAUTH_DIR=/tmp/.docker.xauth; XAUTH=\$XAUTH_DIR/.xauth; touch \$XAUTH; xauth nlist \$DISPLAY | sed -e 's/^..../ffff/' | xauth -f \$XAUTH nmerge -" >> ~/.profile

結局のところ、システムを再起動してユーザーがログインするたびに、コンテナーはXauthorityファイルを自動的に取得します。


4

他の解決策も機能するはずですが、これがの解決策ですdocker-compose

このエラーを修正するには、$ DISPLAYおよび.X11-unixをdockerに渡し、dockerを開始したユーザーにxhostへのアクセスを許可する必要があります。

docker-compose.ymlファイル内:

version: '2'
services:
    node:
        build: .
        container_name: node
        environment:
            - DISPLAY
        volumes:
            - /tmp/.X11-unix:/tmp/.X11-unix

端末またはスクリプト:

  • xhost +si:localuser:$USER
  • xhost +local:docker
  • export DISPLAY=$DISPLAY
  • docker-compose up


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

2

OSX(10.13.6、高シエラ)

@Nickの回答に似ていますが、彼の解決策は私にとってうまくいきませんでした。

最初にを実行してsocat brew install socatをインストールし、XQuartz(https://www.xquartz.org/)をインストールします。

次に、コメントセクションで以下の手順(http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/)を実行しました。

1. in one mac terminal i started:

socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"

2. and in another mac terminal I ran:

docker run -ti --rm \
-e DISPLAY=$(ipconfig getifaddr en0):0 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox

また、debian DockerコンテナーからCLionを起動することもできました。


1

BRIDGEネットワークを備えたDocker。ディスプレイマネージャーlightdmを使用するUbuntu 16.04の場合:

cd /etc/lightdm/lightdm.conf.d
sudo nano user.conf

[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp

よりプライベートな権限を使用できます

xhost +

docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name

1

イメージを既に構築している場合のさらに別の答え:

  1. sudoなしでdockerを呼び出す(docker を修正する方法:権限が拒否された問題が発生した

  2. ホストとコンテナの共有間で同じUSER&home&passwdを共有します(ヒント:ユーザー名の代わりにユーザーIDを使用します)

  3. ドライバーに依存するライブラリがうまく機能するためのdevフォルダー

  4. プラスX11フォワード。

    docker run --name=CONTAINER_NAME --network=host --privileged \
      -v /dev:/dev \
      -v `echo ~`:/home/${USER} \
      -p 8080:80 \
      --user=`id -u ${USER}` \
      --env="DISPLAY" \
      --volume="/etc/group:/etc/group:ro" \
      --volume="/etc/passwd:/etc/passwd:ro" \
      --volume="/etc/shadow:/etc/shadow:ro" \
      --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
      --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
      -it REPO:TAG /bin/bash

あなたが質問するかもしれませんが、非常に多くのものが同じである場合、ドッカーを使用するポイントは何ですか?まあ、私が考えることができる1つの理由は、パッケージの依存性の地獄(https://en.wikipedia.org/wiki/Dependency_hell)を克服するためです)です。

したがって、このタイプの使用法は、開発者により適していると思います。


これは私のために働くだろう唯一のものです。私の目的のために、これを最小化することができました:docker run --network = host --volume = echo ~:/ home / $ {USER} --user = id -u ${USER}--env = "DISPLAY" --volume = "/ etc / passwd:/ etc / passwd:ro "-it REPO:TAG / bin / bash
user1145922 '22

1

次の手順に従って、を使用opencvdockerてUSBカメラからビデオストリームを実行できました。

  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. Qtレンダリング速度を「ネイティブ」に設定し、X11レンダリングエンジンをバイパスしないようにします

    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を使用したリアルタイムおよびビデオ処理オブジェクト検出


「X11 UnixソケットとX認証ファイルを作成する」はファイルを作成せず、変数を定義するだけですか?
MrR
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.