x11 - open - ubuntu docker xserver




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

OSX

JürgenWeigert氏はUbuntuで私にとってうまくいっている最高の答えを持っていますが、OSXではdockerがVirtualBoxの中で動いています。

私は、これらの追加成分を使って作業しています:

  1. Xquartz(OSXはX11サーバーに付属していません)
  2. socatによるソケット転送(brew install socat)
  3. コンテナを起動するbashスクリプト

私は、OSXのこの回答を改善するためのユーザのコメントに感謝します。Xのソケット転送が安全かどうかはわかりませんが、意図的に使用するのはドッカーコンテナーをローカルでのみ実行するためです。

また、マシンの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

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

vncserverなどを設定する画像はありますか?たとえば、Firefoxの周りにスピードバンプの余分なサンドボックスを追加するなどです。


OSX(10.13.6、ハイシエラ)

の答えと似ていますが、彼の解決策は私のためには機能しませんでした。

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

その後、コメントセクションのこちらの手順(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を起動することができました。


Nvidiaドライバを使用したOpenGLレンダリングでは、次のイメージを使用します。

https://github.com/thewtex/docker-opengl-nvidia

他のOpenGL実装では、イメージがホストと同じ実装を持っていることを確認してください。


Xauthorityは新しいシステムでは問題になります。 ドッキング用のコンテナを実行する前に、xhost +による保護を破棄するか、あらかじめ用意されたXauthorityファイルを渡すことができます。 典型的なXauthorityファイルはホスト名に特有のものです。 ドッカーでは、各コンテナは異なるホスト名(ドッカーrun -hで設定)を持つことができますが、ホストシステムと同じコンテナのホスト名を設定しても私の場合は役に立ちませんでした。 xeyes(私はこの例が気に入っています)は単にマジッククッキーを無視し、サーバーに資格情報を渡さないだけです。 したがって、「プロトコルが指定されていません」というエラーメッセージが表示されます。

Xauthorityファイルは、ホスト名が重要でないように記述することができます。 Authentication Familyを '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

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

JürgenWeigertの答えに基づいて、私はいくつかの改善があります:

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ディレクトリをドッキング・コンテナにマウントするために使用されるディレクトリ$ XAUTH_DIRを作成することです。

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

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はコンテナの再起動ポリシーが "always"の場合、自動的に$ XAUTH_DIRディレクトリをマウントします。 ユーザーのログイン後、〜/ .profileに$ XAUTHファイルを作成するコマンドを書くと、コンテナは自動的にこの$ 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ファイルを自動的に取得します。


lord.garbageによる 、VNC、SSH、およびX11転送を使用せずにコンテナ内でGUIアプリケーションを実行する別の解決策があります。 hereでも言及さhereます。


あなたは単に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'

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

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

これは軽量ではありませんが、完全なデスクトップ仮想化によるドッカーの機能のパリティーを提供する素晴らしいソリューションです。 UbuntuとCentOS用のXfce4とIceWMの両方が動作し、 noVNCオプションはブラウザ経由で簡単にアクセスできるようにします。

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

noVNCtigerVNCのvncserverを実行します。 次に、与えられたウィンドウマネージャに対してstartxを呼び出します。 さらに、 libnss_wrapper.soは、ユーザーのパスワード管理をエミュレートするために使用されます。


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

これにより、ドッカーで多くのGUIアプリケーションをパッケージ化することができます。 Firefoxとemacsはこれまでにテストされています。 Firefoxでは、webGLは動作しません。 クロムはまったく動作しません。

編集:サウンド作品!

EDIT2:これを初めて投稿して以来、サブユーザーは大幅に進歩しました。 私は今、 subuser.orgのウェブサイトを持ちXPRAブリッジを介してX11に接続するための新しいセキュリティモデルを持っています。


共有ホスト表示:0は、他の回答に記載されているように、2つの欠点があります。

  • これは、Xセキュリティ漏えいのためにコンテナの隔離を解除します。 例えば、 xevxinput使ったxevや、 xinputxdotoolホストアプリケーションのリモートコントロールが可能xdotool
  • アプリケーションは、X拡張MIT-SHMの共有メモリがないため、レンダリングの不具合やRAMアクセスエラーが発生する可能性があります。 (分離劣化オプション--ipc=hostで固定することもでき--ipc=host )。

この問題を解決するドッカー画像をXephyrで実行するためのスクリプトの例を以下に示します。

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

このスクリプトはいくつかの引数を必要とします。最初にXephyrで実行するホストウィンドウマネージャー、もう1つはドッカーイメージ、もう1つはオプションで実行するイメージコマンドです。 ドッカーでデスクトップ環境を実行するには、ホストウィンドウマネージャの代わりに ":"を使用します。

Xephyrウィンドウを閉じると、ドッカーコンテナアプリケーションが終了します。 ドッキングされたアプリケーションを終了すると、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

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

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

PROS:
+ドッカーコンテナ内にx個のサーバがない
+ vncクライアント/サーバは必要ありません
+ xを使ったsshなし
+はるかに小さいドッカーコンテナ

短所:
- ホスト上でxを使用する(安全なサンドボックス用ではない)

リンクがいつか失敗する場合は、私はここで最も重要な部分を入れました:
ドッカーファイル:

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"コマンドで実行することもできますsh -c "echo script-here"

ヒント:オーディオについては、 https://.com/a/28985715/2835523 : https://.com/a/28985715/2835523


他のソリューションもうまくいくはずですが、ここでは解決策がありdocker-composeます。

そのエラーを修正するには、$ DISPLAYと.X11-unixをドッカーに渡すだけでなく、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