web-dev-qa-db-ja.com

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

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

例えば、Firefox用のスピードバンプサンドボックスを追加できるように、vncserverなどを設定した画像はありますか。

354
Will

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バージョン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
218
creack

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

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
179
Jürgen Weigert

私はこのブログ記事を見つけたので、ここであなたと共有したいと思います。

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

PROS:
+ 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 .

そしてrunコマンド:

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

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

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

59
A. Binzxxxxxx

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

49

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

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

編集:サウンド作品!

編集2:私が最初にこれを投稿してからの時間で、サブユーザーは大きく進歩しました。私は今ウェブサイトup subuser.org 、およびXPRAブリッジングを介してX11 に接続するための新しいセキュリティモデル を持っています。

26
timthelion

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 (タブ) - > set X11リモートアクセス to full
  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

xeyes running on PC

23
Nick

コンテナにXサーバー、vncサーバー、またはsshdデーモンをインストールする手間を省く、軽量なソリューションです。単純化することで得られるものは、セキュリティと分離において失われます。

sshX11フォワーディングを使用してHostマシンに接続すると仮定します。

ホストの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
18
danidiaz

他の回答で述べたように、ホストの表示を共有する: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で向上しました。コンテナユーザーもnot rootです。
  • XクッキーはXephyrディスプレイへのアクセスを制限するために作成されます。

スクリプトはいくつかの引数を想定しています。最初はHostウィンドウマネージャがXephyrで実行され、2番目がdockerイメージ、3番目が実行されるimageコマンドです。 dockerでデスクトップ環境を実行するには、ホストウィンドウマネージャの代わりに ":"を使用してください。

Xephyrウィンドウを閉じると、docker containerアプリケーションは終了します。ドッキングされたアプリケーションを終了すると、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アクセラレーション、Webカメラ、プリンタ共有などの機能をサポートします。

16
mviereck

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

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

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

11
dashesy

JürgenWeigert による答えは本質的にこの解決策を網羅していますが、そこで説明されていることが最初は私には明らかではありませんでした。それで、他の誰かが明確化を必要とする場合に備えて、私はそれについて私の見方を加えます。

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

オンラインの多数のソースが、X11 unixソケットと~/.Xauthorityファイルをコンテナにマウントすることを提案しています。これらの解決策は、なぜその理由が本当に理解されていなくても、運によってうまくいくことが多い。コンテナユーザーはユーザーと同じUIDを使用するので、マジックキー認証は必要ありません。

まず第一に、Xauthorityファイルはモード0600を持っているので、同じUIDを持っていない限りコンテナユーザーはそれを読むことができません。

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

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

それで、あなたがする必要があるのはコンテナのホスト名とHostクッキーと同じ16進数キーで新しいエントリを追加することです(すなわちあなたのデスクトップで走っているXセッション)、例えば:

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

そのキャッチは、クッキーはコンテナ内のxauth addで追加されなければならないということです:

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

それ以外の場合、xauthは、コンテナの外側にしか見えないようにタグを付けます。

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

xauth add hostname/$DISPLAY protocol hexkey

.MIT-MAGIC-COOKIE-1プロトコルを表します。

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

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

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

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

FamilyWildがどのように機能するのか、またはxauthまたはXクライアントがどのように実行されるかに応じてXauthorityファイルからのエントリーをどのようにフィルタリングするのか、私はあまりよく理解していないことを認めます。これに関する追加情報は大歓迎です。

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

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

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

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

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

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

http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ に記載されている解決策は、コンテナの内側からGUIアプリケーションを起動する簡単な方法のようです(私はUbuntu 14.04上でFirefoxを試してみましたが、私は著者によって投稿されたソリューションに小さな追加の変更が必要であることがわかりました。

具体的には、コンテナーを実行するために、著者は言及しました:

    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/

9
Anshuman Manral

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

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

7
Pithikos

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

6
niutech

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ディレクトリを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はコンテナの再起動ポリシーが "always"の場合、自動的に$ 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ファイルを取得します。

5
allenyllee

パーティーには間に合いませんが、XQuartzの道を歩みたくないMacユーザーのために、XvfbVNCを使ってデスクトップ環境(xfce)でFedoraイメージを構築する実用的な例を示します。それは簡単で、うまくいきます:

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
Vince

Nvidiaドライバを使用したOpenGLレンダリングには、次の画像を使用してください。

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

他のOpenGLの実装では、イメージがホストと同じ実装を持つようにしてください。

3
Matt McCormick

他の解決策でもうまくいくはずですが、これはdocker-composeに対する解決策です。

このエラーを修正するには、dockerを起動したユーザーにxhostへのアクセスを許可するだけでなく、$ DISPLAYと.X11-unixをdockerに渡す必要があります。

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
nathangeorge1

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
wedesoft

OSX(10.13.6、High Sierra)

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

まずbrew install socatを実行して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
nommer

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
dabizharoman

あなたがすでにイメージを構築した場合のためのさらに別の答え:

  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

あなたが尋ねるかもしれません、そんなに多くのことが同じならばdockerを使うことのポイントは何ですか?私が考えることができる1つの理由は、パッケージの依存関係の地獄を克服することです( https://en.wikipedia.org/wiki/Dependency_hell )。

そのため、このような使い方は開発者にとってより適していると思います。

0
TingQian LI