Wie können Sie GUI-Anwendungen in einem Docker- Container ausführen ?
Gibt es Bilder, die eingerichtet wurden vncserver
oder so, dass Sie beispielsweise eine zusätzliche Speedbump-Sandbox hinzufügen können, z. B. Firefox?
Wie können Sie GUI-Anwendungen in einem Docker- Container ausführen ?
Gibt es Bilder, die eingerichtet wurden vncserver
oder so, dass Sie beispielsweise eine zusätzliche Speedbump-Sandbox hinzufügen können, z. B. Firefox?
Antworten:
Sie können einfach einen vncserver zusammen mit Firefox installieren :)
Ich habe ein Bild, vnc / Firefox, hier geschoben: docker pull creack/firefox-vnc
Das Bild wurde mit dieser Docker-Datei erstellt:
# 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'
Dadurch wird ein Docker-Container erstellt, auf dem VNC mit dem Kennwort ausgeführt wird 1234
:
Für Docker Version 18 oder neuer:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Für Docker Version 1.3 oder neuer:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Für Docker vor Version 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
docker inspect <container id>
oder einfach docker ps
, dann stellen Sie mit dem gerade gefundenen Port eine Verbindung zur IP Ihres Hosts her.
Xauthority wird bei neueren Systemen zu einem Problem. Ich kann entweder jeden Schutz mit xhost + verwerfen, bevor ich meine Docker-Container ausführe, oder ich kann eine gut vorbereitete Xauthority-Datei übergeben. Typische Xauthority-Dateien sind hostnamenspezifisch. Mit Docker kann jeder Container einen anderen Hostnamen haben (mit Docker-Run -h festgelegt), aber selbst das Festlegen des Hostnamens des Containers, der mit dem Hostsystem identisch ist, hat in meinem Fall nicht geholfen. xeyes (ich mag dieses Beispiel) würde das magische Cookie einfach ignorieren und keine Anmeldeinformationen an den Server übergeben. Daher erhalten wir die Fehlermeldung 'Kein Protokoll angegeben Anzeige kann nicht geöffnet werden'
Die Xauthority-Datei kann so geschrieben werden, dass der Hostname keine Rolle spielt. Wir müssen die Authentifizierungsfamilie auf 'FamilyWild' setzen. Ich bin mir nicht sicher, ob xauth eine richtige Befehlszeile dafür hat. Hier ist ein Beispiel, das xauth und sed kombiniert, um dies zu tun. Wir müssen die ersten 16 Bits der nlist-Ausgabe ändern. Der Wert von FamilyWild ist 65535 oder 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
-v $XSOCK:$XSOCK -v $XAUTH:$XAUTH
kann verkürzt werden zu-v $XSOCK -v $XAUTH
:0
mit $DISPLAY
. Das heißt xauth nlist $DISPLAY | ...
und docker run -ti -e DISPLAY=$DISPLAY ...
. Normalerweise ist das X DISPLAY :0
, aber nicht immer (und besonders nicht, wenn Sie eine Verbindung über ssh -X herstellen).
/tmp/.docker.xauth
Datei mit 600
Berechtigungen. Dies führt dazu, dass xauth im Docker-Container die Datei nicht lesen kann. Sie können dies überprüfen, indem Sie es xauth list
im Docker-Container ausführen. Ich habe chmod 755 $XAUTH
nach dem xauth nlist :0 | ...
Befehl hinzugefügt , um dies zu beheben.
Ich habe gerade diesen Blogeintrag gefunden und möchte ihn hier mit Ihnen teilen, weil ich denke, dass dies der beste Weg ist und es so einfach ist.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
PROS:
+ kein x Server-Zeug im Docker-Container
+ kein vnc-Client / Server erforderlich
+ kein ssh mit x-Weiterleitung
+ viel kleinere Docker-Container
Nachteile:
- Verwenden von x auf dem Host (nicht für sicheres Sandboxing gedacht)
Für den Fall, dass der Link eines Tages fehlschlägt, habe ich hier den wichtigsten Teil
eingefügt: Docker-Datei:
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
Erstellen Sie das Bild:
docker build -t firefox .
und der Befehl run:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
Natürlich können Sie dies auch im Befehl run mit tun sh -c "echo script-here"
TIPP: Audio finden Sie unter: https://stackoverflow.com/a/28985715/2835523
apt-get -y install sudo
, um /etc/sudoers.d
Ordner zu erstellen .
$ xhost +
Mit Docker-Datenvolumes ist es sehr einfach, den Unix-Domain-Socket von xorg im Container verfügbar zu machen.
Zum Beispiel mit einer Docker-Datei wie dieser:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Sie können Folgendes tun:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
Dies entspricht natürlich im Wesentlichen der X-Weiterleitung. Es gewährt dem Container vollen Zugriff auf den xserver auf dem Host. Es wird daher nur empfohlen, wenn Sie dem Inhalt vertrauen.
Hinweis: Wenn Sie Sicherheitsbedenken haben, besteht eine bessere Lösung darin, die App auf die obligatorische oder rollenbasierte Zugriffskontrolle zu beschränken . Docker erreicht eine ziemlich gute Isolation, wurde jedoch für einen anderen Zweck entwickelt. Verwenden Sie AppArmor , SELinux oder GrSecurity , die auf Ihr Problem zugeschnitten sind.
xhost +
auf dem Host.
xhost +local
ist notwendig. Es ist jedoch besser, die ~/.Xauthority
Datei im Container verfügbar zu machen , damit sie sich selbst authentifizieren kann.
Can't open display: :0
. Irgendwelche Ideen?
xhost +si:localuser:$USER
nur den Benutzer autorisiert, der den Container startet.
Sie können auch den Unterbenutzer verwenden: https://github.com/timthelion/subuser
Auf diese Weise können Sie viele GUI-Apps in Docker packen. Firefox und Emacs wurden bisher getestet. Mit Firefox funktioniert webGL jedoch nicht. Chrom funktioniert überhaupt nicht.
EDIT: Sound funktioniert!
EDIT2: In der Zeit, seit ich dies zum ersten Mal gepostet habe, hat sich der Unterbenutzer stark weiterentwickelt. Ich habe jetzt eine Website unter subuser.org und ein neues Sicherheitsmodell für die Verbindung zu X11 über XPRA-Bridging .
Jürgen Weigert hat die beste Antwort, die für mich unter Ubuntu funktioniert hat. Unter OSX läuft Docker jedoch innerhalb von VirtualBox, sodass die Lösung ohne weitere Arbeit nicht funktioniert.
Ich habe es mit diesen zusätzlichen Zutaten zu tun:
Ich würde Benutzerkommentare begrüßen, um diese Antwort für OSX zu verbessern. Ich bin nicht sicher, ob die Socket-Weiterleitung für X sicher ist, aber meine beabsichtigte Verwendung besteht darin, den Docker-Container nur lokal auszuführen.
Außerdem ist das Skript insofern etwas fragil, als es nicht einfach ist, die IP-Adresse des Computers abzurufen, da es sich in unserem lokalen WLAN befindet und es sich also immer um eine zufällige IP handelt.
Das BASH-Skript, mit dem ich den Container starte:
#!/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
Ich kann xeyes und matplotlib dazu bringen, mit diesem Ansatz zu arbeiten.
Unter Windows 7+ ist es mit MobaXterm etwas einfacher:
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
error: XDG_RUNTIME_DIR not set in the environment.
und Error: cannot open display: VAIO:0.0
. Haben Sie so etwas erlebt?
Das Teilen der Hostanzeige: 0 hat, wie in einigen anderen Antworten angegeben, zwei Nachteile:
xev
oder xinput
ist möglich und Fernsteuerung von Hostanwendungen mit xdotool
.--ipc=host
).Unten finden Sie ein Beispielskript zum Ausführen eines Docker-Images in Xephyr, mit dem dieses Problem behoben wird.
--cap-drop ALL --security-opt no-new-privileges
. Auch der Containerbenutzer ist nicht root.Das Skript erwartet einige Argumente, zum einen einen Host-Fenstermanager in Xephyr, zum anderen ein Docker-Image und zum dritten einen auszuführenden Image-Befehl. Verwenden Sie zum Ausführen einer Desktop-Umgebung in Docker ":" anstelle eines Host-Fenstermanagers.
Durch Schließen des Xephyr-Fensters werden Docker-Container-Anwendungen beendet. Durch das Beenden der Docker-Anwendungen wird das Xephyr-Fenster geschlossen.
Beispiele:
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
xephyrdocker : x11docker/lxde
xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom
xephyrdocker-Skript:
#! /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
Dieses Skript wird im x11docker-Wiki verwaltet . Ein erweitertes Skript ist x11docker , das auch Funktionen wie GPU-Beschleunigung, Webcam- und Druckerfreigabe usw. unterstützt.
Hier ist eine einfache Lösung, mit der Sie keinen X
Server, vnc
Server oder sshd
Dämon auf dem Container installieren müssen . Was es an Einfachheit gewinnt, verliert es an Sicherheit und Isolation.
Er geht davon aus, dass Sie auf dem Host - Rechner eine Verbindung über ssh
mit X11
Weiterleitung.
Fügen Sie in der sshd
Konfiguration des Hosts die Zeile hinzu
X11UseLocalhost no
Damit wird der weitergeleitete X-Server-Port auf dem Host auf allen Schnittstellen (nicht nur lo
) und insbesondere auf der virtuellen Docker-Schnittstelle geöffnet docker0
.
Der Container benötigt beim Ausführen Zugriff auf die .Xauthority
Datei, damit er eine Verbindung zum Server herstellen kann. Zu diesem Zweck definieren wir ein schreibgeschütztes Volume, das auf das Home-Verzeichnis auf dem Host verweist (möglicherweise keine gute Idee!), Und setzen die XAUTHORITY
Variable entsprechend.
docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
Das reicht nicht aus, wir müssen auch die Variable DISPLAY vom Host übergeben, aber den Hostnamen durch die IP ersetzen:
-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")
Wir können einen Alias definieren:
alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'
Und testen Sie es so:
dockerX11run centos xeyes
.Xauthority
Datei selbst einbinden : -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
.
X11UseLocalhost
, können Sie auch die zusätzliche Option --net=host
für den docker run
Befehl verwenden ( hier zu finden ).
--net=host
ist eine schlechte Idee, denn wenn Sie jetzt einen Port im Container öffnen, wird er auch im Host geöffnet ...
Während die Antwort von Jürgen Weigert im Wesentlichen diese Lösung abdeckt, war mir zunächst nicht klar, was dort beschrieben wurde. Also werde ich meine Meinung dazu hinzufügen, falls jemand anderes eine Klärung benötigt.
Die relevante Dokumentation ist zunächst die X-Sicherheitsmanpage .
Zahlreiche Online-Quellen schlagen vor, nur den X11-Unix-Socket und die ~/.Xauthority
Datei in den Container zu mounten. Diese Lösungen funktionieren oft durch Glück, ohne wirklich zu verstehen, warum beispielsweise der Containerbenutzer dieselbe UID wie der Benutzer hat, sodass keine Berechtigung für magische Schlüssel erforderlich ist.
Zunächst einmal hat die Xauthority-Datei den Modus 0600, sodass der Containerbenutzer sie nur lesen kann, wenn sie dieselbe UID hat.
Selbst wenn Sie die Datei in den Container kopieren und den Besitz ändern, gibt es noch ein weiteres Problem. Wenn Sie xauth list
auf dem Host und dem Container mit derselben Xauthority
Datei ausgeführt werden, werden verschiedene Einträge aufgelistet. Dies liegt daran xauth
, dass die Einträge je nach Ausführungsort gefiltert werden.
Der X-Client im Container (dh die GUI-App) verhält sich genauso wie xauth
. Mit anderen Worten, das magische Cookie für die X-Sitzung wird nicht auf dem Desktop des Benutzers ausgeführt. Stattdessen werden die Einträge für alle "Remote" X-Sitzungen angezeigt, die Sie zuvor geöffnet haben (siehe unten).
Sie müssen also einen neuen Eintrag mit dem Hostnamen des Containers und demselben Hex-Schlüssel wie das Host-Cookie hinzufügen (dh die X-Sitzung, die auf Ihrem Desktop ausgeführt wird), z.
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
Der Haken ist, dass der Cookie im xauth add
Inneren des Behälters hinzugefügt werden muss :
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Andernfalls wird es so xauth
markiert, dass es nur außerhalb des Containers angezeigt wird.
Das Format für diesen Befehl lautet:
xauth add hostname/$DISPLAY protocol hexkey
Wo .
steht das MIT-MAGIC-COOKIE-1
Protokoll.
Hinweis: Es ist nicht erforderlich, .Xauthority
den Container zu kopieren oder zu binden . Erstellen Sie einfach eine leere Datei, wie gezeigt, und fügen Sie das Cookie hinzu.
Die Antwort von Jürgen Weigert umgeht dies, indem er mithilfe des FamilyWild
Verbindungstyps eine neue Berechtigungsdatei auf dem Host erstellt und in den Container kopiert. Beachten Sie, dass zuerst der Hex-Schlüssel für die aktuelle X-Sitzung aus der ~/.Xauthority
Verwendung extrahiert wird xauth nlist
.
Die wesentlichen Schritte sind also:
FamilyWild
Verbindungstyp).Ich gebe zu, dass ich nicht sehr gut verstehe, wie es FamilyWild
funktioniert oder wie oder wie xauth
X-Clients Einträge aus der Xauthority-Datei filtern, je nachdem, wo sie ausgeführt werden. Zusätzliche Informationen hierzu sind willkommen.
Wenn Sie Ihre Docker-App verteilen möchten, benötigen Sie ein Startskript zum Ausführen des Containers, der den Hex-Schlüssel für die X-Sitzung des Benutzers erhält, und importiert ihn auf eine der beiden zuvor erläuterten Arten in den Container.
Es hilft auch, die Mechanismen des Autorisierungsprozesses zu verstehen:
$DISPLAY
./tmp/.X11-unix
im Container bereitgestellten Verzeichnis an den X-Server weiter .Hinweis: Der X11 Unix-Socket muss noch im Container bereitgestellt werden, da der Container sonst keine Route zum X-Server hat. Die meisten Distributionen deaktivieren aus Sicherheitsgründen standardmäßig den TCP-Zugriff auf den X-Server.
Für zusätzliche Informationen und um besser zu verstehen, wie die X-Client / Server-Beziehung funktioniert, ist es auch hilfreich, den Beispielfall der SSH X-Weiterleitung zu betrachten:
$DISPLAY
in der SSH-Sitzung wird so festgelegt, dass er auf den eigenen X-Server verweist.xauth
, um ein neues Cookie für den Remote-Host zu erstellen und es den Xauthority
Dateien sowohl für den lokalen als auch für den Remote-Benutzer hinzuzufügen.Dies ist nicht leicht, aber eine nette Lösung, die Docker-Feature-Parität mit vollständiger Desktop-Virtualisierung bietet. Sowohl Xfce4 als auch IceWM für Ubuntu und CentOS funktionieren, und die noVNC
Option ermöglicht einen einfachen Zugriff über einen Browser.
https://github.com/ConSol/docker-headless-vnc-container
Es läuft noVNC
genauso gut wie tigerVNC
der vncserver. Dann wird ein startx
bestimmter Fenstermanager aufgerufen. Darüber hinaus libnss_wrapper.so
wird die Kennwortverwaltung für die Benutzer emuliert.
xpra
Docker ausprobiert , das X ohne Root ist. Es xpra
war die am besten geeignete IMO und ist effizienter als VNC.
--device /dev/...
an das Docker und legen die erforderlichen --cap
Berechtigungen fest. Das macht den Zweck der Eindämmung zunichte, aber Sie können Geräte passieren. Mit einigen Optimierungen sollte es möglich sein, GNOME / KDE unter VNC auszuführen. Ich habe mehrere X im Docker mit NVIDIA-Karten (kein VNC oder Xpra) ausgeführt, so dass dies sicherlich machbar ist.
Die unter http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ angegebene Lösung scheint eine einfache Möglichkeit zu sein, GUI-Anwendungen aus den Containern heraus zu starten (ich habe es mit Firefox versucht über Ubuntu 14.04), aber ich habe festgestellt, dass eine kleine zusätzliche Änderung an der vom Autor veröffentlichten Lösung erforderlich ist.
Insbesondere zum Ausführen des Containers hat der Autor Folgendes erwähnt:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
Aber ich fand, dass (basierend auf einem bestimmten Kommentar auf der gleichen Seite) zwei zusätzliche Optionen
-v $HOME/.Xauthority:$HOME/.Xauthority
und
-net=host
müssen beim Ausführen des Containers angegeben werden, damit Firefox ordnungsgemäß funktioniert:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $HOME/.Xauthority:$HOME/.Xauthority \
-net=host \
firefox
Ich habe ein Docker-Bild mit den Informationen auf dieser Seite und diesen zusätzlichen Ergebnissen erstellt: https://hub.docker.com/r/amanral/ubuntu-firefox/
/tmp/.X11-unix
Steckdose passieren müssen . Es funktioniert nur mit Montage .Xauthority
und --net=host
.
/tmp/.X11-unix
als Volume funktioniert nicht mehr, da Docker die Bereitstellung von Volumes aus klebrigen Verzeichnissen stillschweigend ablehnt.
--network=host
tut. Dadurch erhält Ihr Container vollen Zugriff auf den Netzwerkstapel des Hosts, was je nach dem, was Sie versuchen, unerwünscht sein kann. Wenn Sie nur daran arbeiten, containerisierte GUIs auf Ihrem Desktop auszuführen, sollte dies keine Rolle spielen.
Es gibt eine andere Lösung von lord.garbage , um GUI-Apps in einem Container ohne VNC- , SSH- und X11-Weiterleitung auszuführen. Es wird auch hier erwähnt .
Wenn Sie eine GUI-Anwendung ohne Kopf ausführen möchten, lesen Sie hier . Sie müssen lediglich einen virtuellen Monitor mit xvfb
oder einer ähnlichen Software erstellen . Dies ist sehr hilfreich, wenn Sie Selenium-Tests beispielsweise mit Browsern ausführen möchten.
Nirgendwo erwähnt wird, dass einige Software selbst Sandboxing mit Linux-Containern verwenden. So wird beispielsweise Chrome niemals normal ausgeführt, wenn Sie --privileged
beim Ausführen des Containers nicht das entsprechende Flag verwenden .
Ich bin zu spät zur Party, aber für Mac-Benutzer, die den XQuartz-Pfad nicht beschreiten möchten, ist hier ein funktionierendes Beispiel, das ein Fedora-Image mit einer Desktop-Umgebung (xfce) erstellt, die Xvfb
und verwendet VNC
. Es ist einfach und funktioniert:
Auf einem Mac können Sie einfach mit der Bildschirmfreigabe (Standard) darauf zugreifen und eine Verbindung herstellen 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
Überprüfen Sie die verknüpfte Readme-Datei auf Build- und Run-Befehle, wenn Sie möchten / benötigen.
Aufgrund der Antwort von Jürgen Weigert habe ich einige Verbesserungen:
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
Der einzige Unterschied besteht darin, dass ein Verzeichnis $ XAUTH_DIR erstellt wird, in dem die Datei $ XAUTH abgelegt und das Verzeichnis $ XAUTH_DIR anstelle der Datei $ XAUTH in den Docker-Container eingefügt wird.
Der Vorteil dieser Methode besteht darin, dass Sie in /etc/rc.local einen Befehl schreiben können, mit dem ein leerer Ordner mit dem Namen $ XAUTH_DIR in / tmp erstellt und dessen Modus auf 777 geändert wird.
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
Beim Neustart des Systems stellt Docker vor der Benutzeranmeldung das Verzeichnis $ XAUTH_DIR automatisch bereit, wenn die Neustartrichtlinie des Containers "immer" lautet. Nach der Benutzeranmeldung können Sie einen Befehl in ~ / .profile schreiben, mit dem die $ XAUTH-Datei erstellt werden soll. Der Container verwendet dann automatisch diese $ XAUTH-Datei.
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
Schließlich erhält der Container bei jedem Neustart des Systems und bei der Benutzeranmeldung automatisch die Xauthority-Datei.
Die anderen Lösungen sollten funktionieren, aber hier ist eine Lösung für docker-compose
.
Um diesen Fehler zu beheben, müssen Sie $ DISPLAY und .X11-unix an Docker übergeben und dem Benutzer, der Docker gestartet hat, Zugriff auf xhost gewähren.
Innerhalb der docker-compose.yml
Datei:
version: '2'
services:
node:
build: .
container_name: node
environment:
- DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
Im Terminal oder Skript:
xhost +si:localuser:$USER
xhost +local:docker
export DISPLAY=$DISPLAY
docker-compose up
Verwenden Sie für OpenGL-Rendering mit dem Nvidia-Treiber das folgende Bild:
https://github.com/thewtex/docker-opengl-nvidia
Stellen Sie bei anderen OpenGL-Implementierungen sicher, dass das Image dieselbe Implementierung wie der Host hat.
Ähnlich wie @Nicks Antwort, aber seine Lösung hat bei mir nicht funktioniert.
Installieren Sie zuerst socat, indem Sie dies tun brew install socat
, und installieren Sie XQuartz ( https://www.xquartz.org/ ).
Befolgen Sie dann diese Schritte hier ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ ) im Kommentarbereich:
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
Ich konnte CLion auch von meinem Debian-Docker-Container aus starten.
Docker mit BRIDGE-Netzwerk. für Ubuntu 16.04 mit Display Manager lightdm:
cd /etc/lightdm/lightdm.conf.d
sudo nano user.conf
[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp
Sie können mehr private Berechtigungen verwenden
xhost +
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name
Noch eine Antwort für den Fall, dass Sie das Image bereits erstellt haben:
Docker ohne Sudo aufrufen ( So beheben Sie Docker: Problem mit Berechtigung verweigert )
Teilen Sie den gleichen USER & home & passwd zwischen Host- und Container-Share (Tipps: Verwenden Sie die Benutzer-ID anstelle des Benutzernamens).
Der Dev-Ordner für treiberabhängige Bibliotheken funktioniert einwandfrei
plus X11 vorwärts.
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
Sie fragen sich vielleicht, was bringt es, Docker zu verwenden, wenn so viele Dinge gleich sind? Ein Grund, den ich mir vorstellen kann, ist die Überwindung der Hölle der Paketabhängigkeit ( https://en.wikipedia.org/wiki/Dependency_hell) ).
Daher ist diese Art der Verwendung meiner Meinung nach eher für Entwickler geeignet.
echo ~
: / home / $ {USER} --user = id -u ${USER}
--env = "DISPLAY" --volume = "/ etc. / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
Ich habe mithilfe von opencv
in einen Videostream von einer USB-Kamera ausgeführt, indem ich die docker
folgenden Schritte ausgeführt habe:
Lassen Sie Docker auf den X-Server zugreifen
xhost +local:docker
Erstellen Sie den X11 Unix-Socket und die X-Authentifizierungsdatei
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
Fügen Sie die richtigen Berechtigungen hinzu
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
Stellen Sie die Qt-Rendergeschwindigkeit auf "native" ein, damit die X11-Rendering-Engine nicht umgangen wird
export QT_GRAPHICSSYSTEM=native
Weisen Sie Qt an, MIT-SHM (Shared Memory) nicht zu verwenden. Auf diese Weise sollte es auch sicherer sein
export QT_X11_NO_MITSHM=1
Aktualisieren Sie den Docker-Ausführungsbefehl
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
Hinweis: Wenn Sie das Projekt abgeschlossen haben, geben Sie die Zugriffssteuerungen auf ihren Standardwert zurück. xhost -local:docker
Weitere Details: Verwenden von GUIs mit Docker
Gutschrift: Echtzeit- und Videoverarbeitungsobjekterkennung mit Tensorflow, OpenCV und Docker