Docker コンテナーでGUIアプリケーションを実行するにはどうすればよいですか。
例えば、Firefox用のスピードバンプサンドボックスを追加できるように、vncserver
などを設定した画像はありますか。
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
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
私はこのブログ記事を見つけたので、ここであなたと共有したいと思います。
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
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はかなり優れた分離を実現しますが、異なる目的を念頭に置いて設計されました。 AppArmor 、 SELinux 、または GrSecurity を使用してください。これらは問題に対処するように設計されています。
サブユーザーを使用することもできます: https://github.com/timthelion/subuser
これにより、多くのguiアプリをdockerにパッケージすることができます。 Firefoxとemacsはこれまでにテストされています。 Firefoxでは、webGLは動作しません。クロムはまったく機能しません。
編集:サウンド作品!
編集2:私が最初にこれを投稿してからの時間で、サブユーザーは大きく進歩しました。私は今ウェブサイトup subuser.org 、およびXPRAブリッジングを介してX11 に接続するための新しいセキュリティモデル を持っています。
JürgenWeigert はUbuntuで私のために働いた最良の答えを持っています、しかしOSXの上で、dockerはVirtualBoxの中で動くので、解決策はそれ以上の仕事なしでは働きません。
私はそれがこれらの追加の成分で働いていることを持っています:
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では、もう少し簡単です。
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
コンテナにX
サーバー、vnc
サーバー、またはsshd
デーモンをインストールする手間を省く、軽量なソリューションです。単純化することで得られるものは、セキュリティと分離において失われます。
ssh
とX11
フォワーディングを使用して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
他の回答で述べたように、ホストの表示を共有する:0には2つの欠点があります。
xev
またはxinput
によるキーロギング、およびxdotool
によるホストアプリケーションのリモート制御が可能です。--ipc=Host
で修正することもできます)。この問題に対処するXephyrでdockerイメージを実行するためのスクリプト例を以下に示します。
--cap-drop ALL --security-opt no-new-privileges
で向上しました。コンテナユーザーもnot rootです。スクリプトはいくつかの引数を想定しています。最初は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カメラ、プリンタ共有などの機能をサポートします。
これは軽量ではありませんが、フルデスクトップ仮想化と同等の機能を提供する優れたソリューションです。 Xfce4とIceWM for UbuntuとCentOSの両方が動作し、noVNC
オプションはブラウザから簡単にアクセスできるようにします。
https://github.com/ConSol/docker-headless-vnc-container
noVNC
のvncserverと同様にtigerVNC
も実行します。それからそれは与えられたウィンドウマネージャに対してstartx
を呼び出します。さらに、libnss_wrapper.so
はユーザーのパスワード管理をエミュレートするために使用されます。
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進キーを最初に抽出することに注意してください。
したがって、重要な手順は次のとおりです。
FamilyWild
接続タイプを使用してクッキーを作成します)。FamilyWild
がどのように機能するのか、またはxauth
またはXクライアントがどのように実行されるかに応じてXauthorityファイルからのエントリーをどのようにフィルタリングするのか、私はあまりよく理解していないことを認めます。これに関する追加情報は大歓迎です。
Dockerアプリを配布したい場合は、ユーザーのXセッション用の16進キーを取得し、それを前述の2つの方法のいずれかでコンテナーにインポートするコンテナーを実行するための開始スクリプトが必要になります。
また、承認プロセスの仕組みを理解するのにも役立ちます。
$DISPLAY
の値と一致するクッキーエントリを探す。/tmp/.X11-unix
ディレクトリ内の適切なソケットを介して、Xサーバーにその承認要求とともにそれを渡します。注: それでもX11 Unixソケットをコンテナーにマウントする必要があります。そうしないと、コンテナーにXサーバーへの経路がありません。セキュリティ上の理由から、ほとんどのディストリビューションではデフォルトでXサーバーへのTCPアクセスを無効にしています。
追加情報、およびXクライアント/サーバーの関係がどのように機能するのかをよりよく理解するために、SSH X転送の例のケースを調べることも役立ちます。
$DISPLAY
の値をそれ自身のXサーバーを指すように設定します。xauth
を使用してリモートホスト用の新しいクッキーを作成し、それをローカルユーザーとリモートユーザーの両方のXauthority
ファイルに追加します。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/
GUIアプリケーションをヘッドレスで実行したい場合は、 ここ を読んでください。あなたがしなければならないのはxvfb
または他の同様のソフトウェアで仮想モニターを作成することです。たとえばブラウザでSeleniumテストを実行したい場合、これは非常に役に立ちます。
どこにも述べられていないことは、いくつかのソフトウェアはそれ自身が実際にLinuxコンテナでサンドボックスを使用しているということです。したがって、たとえば、コンテナの実行時に適切なフラグ--privileged
を使用しないと、Chromeは正常に実行されません。
lord.garbageによる別の解決策 は、VNC、SSH、およびX11転送を使用せずにコンテナ内でGUIアプリケーションを実行することです。 ここ とも言われます。
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ファイルを取得します。
パーティーには間に合いませんが、XQuartzの道を歩みたくないMacユーザーのために、Xvfb
とVNC
を使ってデスクトップ環境(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 をビルドして実行するコマンドを確認してください。
Nvidiaドライバを使用したOpenGLレンダリングには、次の画像を使用してください。
https://github.com/thewtex/docker-opengl-nvidia
他のOpenGLの実装では、イメージがホストと同じ実装を持つようにしてください。
他の解決策でもうまくいくはずですが、これは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
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
@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を起動することができました。
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
あなたがすでにイメージを構築した場合のためのさらに別の答え:
sudoなしでdockerを起動する( dockerを修正する方法:許可拒否の問題 )
ホストとコンテナの共有で同じUSER&home&passwdを共有する(ヒント:ユーザー名の代わりにユーザーIDを使用)
ドライバに依存するライブラリが動作するためのdevフォルダ
プラス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 )。
そのため、このような使い方は開発者にとってより適していると思います。