Pouvez-vous lancer des applications GUI dans un conteneur Docker?
comment exécuter des applications GUI dans un conteneur Docker ?
y a - t - il des images qui mettent en place vncserver
ou quelque chose pour que vous puissiez-par exemple-ajouter un bac à sable speedbump supplémentaire autour de say Firefox?
19 réponses
vous pouvez simplement installer un vncserver avec Firefox:)
j'ai poussé une image, vnc / firefox, ici: docker pull creack/firefox-vnc
l'image a été réalisée avec ce fichier 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'
cela créera un conteneur Docker tournant VNC avec le mot de passe 1234
:
pour Docker version 1.3 ou plus récente:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
pour Docker avant la version 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
Xauthority devient un problème avec les nouveaux systèmes. Je peux soit rejeter toute protection avec xhost + avant d'exécuter mes conteneurs docker, ou je peux passer dans un fichier Xauthority bien préparé. Les fichiers XAUTHORITY typiques sont spécifiques au nom d'hôte. Avec docker, chaque conteneur peut avoir un nom d'hôte différent (défini avec docker run-h), mais même définir le nom d'hôte du conteneur identique au système hôte n'a pas aidé dans mon cas. xeyes (j'aime cet exemple) ignorerait simplement le cookie magique et ne passe Aucun mot de passe au serveur. Nous obtenons donc un message d'erreur 'aucun protocole spécifié ne peut ouvrir l'affichage'
le fichier Xauthority peut être écrit d'une manière telle que le nom d'hôte n'a pas d'importance. Nous devons définir la famille D'authentification à 'FamilyWild'. Je ne suis pas sûr, si xauth a une ligne de commande appropriée pour cela, alors voici un exemple qui combine xauth et sed pour le faire. Nous devons changer les 16 premiers bits de la sortie nlist. La valeur de FamilyWild est de 65535 ou 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
je viens de trouver cette entrée de blog et je veux la partager ici avec vous parce que je pense que c'est la meilleure façon de le faire et il est si facile.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker /
PROS:
+ aucun contenu de serveur x dans le conteneur docker
+ pas de client / serveur vnc nécessaire
+ pas de ssh avec le x forwarding
+ conteneurs docker beaucoup plus petits
CONS:
-l'utilisation de x sur l'hôte (pas destiné à secure-sandboxing)
au cas où le lien échouerait un jour, j'ai mis la partie la plus importante ici:
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
construire l'image:
docker build -t firefox .
et la commande run:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
bien sûr, vous pouvez aussi le faire ceci dans la commande run avec sh -c "echo script-here"
conseil: pour l'audio jetez un oeil à: https://stackoverflow.com/a/28985715/2835523
avec les volumes de données docker, il est très facile d'exposer la socket de domaine unix de xorg à l'intérieur du conteneur.
par exemple, avec un fichier Dockerfile comme celui-ci:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
vous pourriez faire ce qui suit:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
ceci est bien sûr essentiellement le même que X-forwarding. Il accorde au conteneur un accès complet au xserver sur l'hôte, donc il est seulement recommandé si vous faites confiance à ce qui est à l'intérieur.
Note: si vous êtes préoccupé par la sécurité, une meilleure solution serait de limiter l'application avec obligatoire - ou basé sur le rôle- contrôle d'accès. Docker obtient assez bon isolement, mais il a été conçu avec un but différent à l'esprit. Utilisez AppArmor , SELinux , ou GrSecurity , qui ont été conçus pour répondre à votre préoccupation.
vous pouvez également utiliser subuser: https://github.com/timthelion/subuser
cela vous permet d'empaqueter de nombreuses applications gui dans docker. Firefox et emacs ont été testés jusqu'à présent. Avec firefox, webGL ne fonctionne pas. Chrome ne fonctionne pas du tout.
EDIT: le Son fonctionne!
EDIT2: depuis que j'ai posté ceci, subuser a beaucoup progressé. J'ai maintenant un site web subuser.org , et un nouveau modèle de sécurité pour se connecter à X11 via xpra pont .
OSX
Jürgen Weigert a la meilleure réponse qui a fonctionné pour moi sur Ubuntu, cependant sur OSX, docker fonctionne à l'intérieur de VirtualBox et donc la solution ne fonctionne pas sans plus de travail.
Je l'ai obtenu travaillant avec ces ingrédients supplémentaires:
- Xquartz (OSX n'est plus fourni avec X11 server)
- transfert de socket avec socat (brew install socat)
- bash script pour lancer le conteneur
j'apprécierais les commentaires des utilisateurs pour améliorer cette réponse pour OSX, Je ne suis pas sûr si socket forwarding for X est sécurisé, mais mon utilisation prévue est pour exécuter le conteneur docker localement seulement.
en outre, le script est un peu fragile en ce qu'il n'est pas facile d'obtenir l'adresse IP de la machine puisque c'est sur notre réseau local sans fil donc c'est toujours une adresse IP aléatoire.
Le script BASH que j'utilise pour lancer le conteneur:
#!/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 }')
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
je suis capable de faire travailler xeyes et matplotlib avec cette approche.
Windows 7+
C'est un peu plus facile sur Windows 7+ avec MobaXterm:
- Installer MobaXterm pour windows
- Start MobaXterm
- Configurer le serveur X: Paramètres -> X11 (onglet) -> mettre X11 accès à distance à complet "1519380920
- utilisez ce script BASH pour lancer le conteneur
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
Voici une solution légère qui évite d'avoir à installer tout X
serveur, vnc
serveur ou sshd
démon sur le conteneur. Ce qu'elle gagne en simplicité, elle le perd en sécurité et en isolement.
il suppose que vous vous connectez à la machine hôte en utilisant ssh
avec X11
forwarding.
dans la configuration sshd
de l'hôte, ajouter la ligne
X11UseLocalhost no
de sorte que le port serveur X transmis sur l'hôte est ouvert sur toutes les interfaces (pas seulement lo
) et en particulier sur L'interface virtuelle Docker, docker0
.
le conteneur, lorsqu'il est lancé, doit avoir accès au fichier .Xauthority
pour pouvoir se connecter au serveur. Pour ce faire, nous définissons un volume en lecture seule pointant vers le répertoire d'accueil de l'hôte (peut-être pas une bonne idée!) et définit également la variable XAUTHORITY
en conséquence.
docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
cela ne suffit pas, nous devons aussi passer la variable D'affichage de l'hôte, mais en remplaçant le nom d'hôte par l'ip:
-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")
nous pouvons définir un alias:
alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'
et le tester comme ceci:
dockerX11run centos xeyes
Partage d'accueil affichage :0, comme indiqué dans d'autres réponses, a deux inconvénients:
- il casse l'isolation du conteneur en raison de quelques fuites de sécurité. Par exemple, keylogging avec
xev
ouxinput
est possible, et la commande à distance des applications hôtes avecxdotool
.
Les Applications - peuvent avoir des problèmes de rendu et de mauvaises erreurs D'accès à la mémoire vive en raison de l'absence de mémoire partagée pour L'extension X MIT-SHM. (Peut également être fixé avec isolation option dégradante
--ipc=host
).
ci-dessous un exemple de script pour exécuter une image de docker dans Xephyr qui traite de ces problèmes.
- il évite les fuites de sécurité X car les applications docker tournent sur un serveur X imbriqué.
- MIT-SHM est désactivé pour éviter les problèmes d'accès à la mémoire vive.
- la sécurité des conteneurs est améliorée avec
--cap-drop ALL --security-opt no-new-privileges
. Aussi l'utilisateur de conteneur est pas de racine. - un cookie X est créé pour restreindre l'accès à l'affichage de Xephyr.
le script attend quelques arguments, d'abord un gestionnaire de fenêtre hôte à exécuter dans Xephyr, ensuite une image docker, optionnellement troisième une commande image à exécuter. Pour exécuter un environnement de bureau dans docker, utilisez ":" au lieu d'un gestionnaire de fenêtres hôte.
fermeture de la fenêtre Xephyr terminates Docker container applications. La résiliation de la dockered applications ferme la fenêtre Xephyr.
exemples:
-
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
-
xephyrdocker : x11docker/lxde
-
xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom
xephyrdocker script:
#! /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="" && 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
il ne s'agit pas d'une solution légère, mais d'une solution agréable qui donne la parité des fonctionnalités du docker avec la virtualisation complète du bureau. Tant Xfce4 que IceWM pour Ubuntu et CentOS fonctionnent, et l'option noVNC
permet un accès facile à travers un navigateur.
https://github.com/ConSol/docker-headless-vnc-container
il exécute noVNC
ainsi que tigerVNC
's vncserver. Puis il appelle startx
pour le Gestionnaire de fenêtre donné. En outre, libnss_wrapper.so
est utilisé pour émuler la gestion de mot de passe pour les utilisateurs.
la solution donnée à http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker / ne semble être un moyen facile de commencer des applications GUI à partir de l'intérieur des conteneurs ( j'ai essayé pour firefox sur ubuntu 14.04), mais j'ai trouvé qu'un petit changement supplémentaire est nécessaire à la solution affichée par l'auteur.
spécifiquement, pour faire fonctionner le conteneur, l'auteur a mentionné:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
mais j'ai trouvé que (d'après un commentaire particulier sur le même site) que deux options supplémentaires
-v $HOME/.Xauthority:$HOME/.Xauthority
et
-net=host
doit être spécifié lors de l'utilisation du conteneur pour que firefox fonctionne correctement:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $HOME/.Xauthority:$HOME/.Xauthority \
-net=host \
firefox
j'ai créé une image docker avec les informations sur cette page et ces résultats supplémentaires: https://hub.docker.com/r/amanral/ubuntu-firefox /
Il y a une autre solution par le seigneur.poubelle pour exécuter des applications GUI dans un conteneur sans utiliser VNC, SSH et X11 forwarding. Il est mentionné ici .
si vous voulez exécuter une application GUI sans tête, alors lire ici . Ce que vous devez faire est de créer un moniteur virtuel avec xvfb
ou un autre logiciel similaire. Ceci est très utile si vous voulez exécuter des tests de sélénium par exemple avec des navigateurs.
ce qui n'est mentionné nulle part, c'est que certains logiciels utilisent en fait eux-mêmes la boxe avec des conteneurs Linux. Par exemple, Chrome ne fonctionnera jamais normalement si vous n'utilisez pas indicateur approprié --privileged
lors de l'exécution du conteneur.
basé sur Jürgen Weigert 'S réponse, j'ai une certaine amélioration:
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
la seule différence est qu'il crée un répertoire $XAUTH_DIR qui est utilisé pour placer le fichier $XAUTH et monter le répertoire $XAUTH_DIR au lieu du fichier $XAUTH dans le conteneur docker.
L'avantage de cette méthode est que vous pouvez écrire une commande dans /etc/rc.local qui est de créer un dossier vide nommé $XAUTH_DIR dans /tmp et de changer son mode au 777.
tr '\n' '"151910920"0' < /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 '"151910920"0' '\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
lors du redémarrage du système, avant l'ouverture de session de l'utilisateur, docker montera le répertoire $XAUTH_DIR automatiquement si la Politique de redémarrage du conteneur est "toujours". Après connexion de l'utilisateur, vous pouvez écrire une commande dans ~/.profil qui est de créer le fichier $XAUTH, puis le conteneur utilisera automatiquement ce fichier $XAUTH.
tr '\n' '"151920920"0' < ~/.profile | sudo tee ~/.profile >/dev/null
sed -i 's|\x00XAUTH_DIR=.*-\x00|\x00|' ~/.profile
tr '"151920920"0' '\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
après tout, le conteneur obtiendra automatiquement le fichier Xauthority chaque fois que le système redémarre et que l'utilisateur se connecte.
pour le rendu OpenGL avec le pilote Nvidia, utilisez l'image suivante:
https://github.com/thewtex/docker-opengl-nvidia
pour les autres implémentations OpenGL, assurez-vous que l'image a la même implémentation que le host.
je suis en retard pour la fête, mais pour les utilisateurs Mac qui ne veulent pas suivre le chemin XQuartz, voici un exemple qui construit une image Fedora, avec un environnement de bureau (xfce) en utilisant Xvfb
et VNC
. C'est simple, et fonctionne:
- https://github.com/ddual/docker_recipes#fedora-with-an-x-window-system
- https://github.com/ddual/docker_recipes/tree/master/fedora_gui
sur un Mac, vous pouvez simplement y accéder en utilisant l'application partage D'écran (par défaut), en se connectant à 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
cochez le lien readme pour construire et exécuter des commandes si vous voulez/avez besoin.
alors que la réponse de Jürgen Weigert couvre essentiellement cette solution, il n'était pas clair pour moi d'abord ce qui était décrit là. Je vais donc ajouter mon point de vue, au cas où quelqu'un d'autre aurait besoin de clarification.
tout d'abord, la documentation pertinente est le X page de manuel de sécurité .
de nombreuses sources en ligne suggèrent simplement de monter la socket unix X11 et le fichier ~/.Xauthority
dans le conteneur. Ces solutions fonctionnent souvent par chance, sans vraiment comprendre pourquoi, par exemple l'utilisateur de conteneur finit avec le même UID que l'utilisateur, il n'y a donc pas besoin d'autorisation clé magique.
tout d'abord, le fichier Xauthority a le mode 0600, donc l'utilisateur du conteneur ne pourra pas le lire à moins qu'il n'ait le même UID.
même si vous copiez le fichier dans le conteneur, et changez la propriété, il y a encore un autre problème. Si vous exécutez xauth list
sur l'hôte et le conteneur, avec le même fichier Xauthority
, vous verrez différentes entrées listées. C'est parce que xauth
filtre les entrées en fonction de l'endroit où elles sont exécutées.
le client X dans le conteneur (i.e. GUI app) se comportera comme xauth
. En d'autres termes, il ne voit pas le cookie magique pour la session X qui s'exécute sur le bureau de l'utilisateur. Au lieu de cela, il voit les entrées pour toutes les sessions X "distantes" que vous avez ouvertes précédemment (expliqué dessous.)
ainsi, ce que vous devez faire est d'ajouter une nouvelle entrée avec le nom d'hôte du conteneur et la même clé hexadécimale que le cookie hôte (c.-à-d. la session X tournant sur votre bureau), par exemple:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
le problème est que le biscuit doit être ajouté avec xauth add
à l'intérieur du conteneur:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
sinon, xauth
l'étiquette d'une façon qu'il est seulement vu à l'extérieur du conteneur.
le le format de cette commande est:
xauth add hostname/$DISPLAY protocol hexkey
où .
représente le protocole MIT-MAGIC-COOKIE-1
.
Note: il n'est pas nécessaire de copier ou de lier .Xauthority
dans le conteneur. Il suffit de créer un fichier vierge, comme indiqué, et ajouter le cookie.
Jürgen Weigert 's réponse permet de contourner cela en utilisant le FamilyWild
type de connexion pour créer une nouvelle autorité fichier sur l'hôte et le copier dans le conteneur. Notez qu'il extrait d'abord la touche hex pour la session X courante de ~/.Xauthority
en utilisant xauth nlist
.
ainsi les étapes essentielles sont:
- extraire la clé hexadécimale du cookie pour la session X courante de l'utilisateur.
- créer un nouveau fichier Xauthority dans le conteneur, avec le nom d'hôte du conteneur et la clé hex partagée (ou créer un cookie avec le
FamilyWild
type de connexion).
j'admets que je ne comprends pas très bien comment FamilyWild
fonctionne, ou comment les clients xauth
ou X filtrent les entrées du fichier Xauthority selon l'endroit où elles sont exécutées. Des informations supplémentaires sur ce sujet est la bienvenue.
si vous voulez distribuer votre application Docker, vous aurez besoin d'un script de démarrage pour exécuter le conteneur qui obtient la clé hex pour la session X de l'utilisateur, et l'importe dans le conteneur dans l'un des deux façons expliquées précédemment.
il est également utile de comprendre les mécanismes du processus d'autorisation:
- un client X (c.-à-d. application GUI) exécuté dans le conteneur cherche dans le fichier Xauthority une entrée de cookie qui correspond au nom d'hôte du conteneur et à la valeur de
$DISPLAY
. - si une entrée correspondante est trouvée, le client X la transmet avec sa demande d'autorisation au serveur X, via le prise appropriée dans le répertoire
/tmp/.X11-unix
monté dans le conteneur.
Note: la socket Unix X11 doit encore être montée dans le conteneur, ou le conteneur n'aura pas de route vers le serveur X. La plupart des distributions désactivent L'accès TCP au serveur X par défaut pour des raisons de sécurité.
pour de plus amples informations, et pour mieux comprendre comment fonctionne la relation client/serveur X, il est également utile pour regarder l'exemple de SSH x forwarding:
- le serveur SSH tournant sur une machine distante émule son propre serveur X.
- définit la valeur de
$DISPLAY
dans la session SSH pour pointer vers son propre serveur X. - il utilise
xauth
pour créer un nouveau cookie pour l'hôte distant, et l'ajoute aux fichiersXauthority
pour les utilisateurs locaux et distants. - quand les applications GUI sont au début, ils parlent au serveur X émulé de SSH.
- le serveur SSH transmet ces données au client SSH sur votre bureau local.
- le client SSH Local envoie les données à la session du serveur X qui tourne sur votre bureau, comme si le client SSH était en fait un client X (i.e. application GUI).
- le serveur X utilise les données reçues pour afficher l'interface graphique sur votre bureau.
- au début de cet échange, le distance X client envoie une demande d'autorisation, en utilisant le cookie qui vient d'être créé. Le serveur X local le compare avec sa copie locale.
vous pouvez autoriser l'utilisateur du Docker (ici: root) à accéder à L'affichage 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
les autres solutions devraient fonctionner, mais voici une solution pour docker-compose
.
pour corriger cette erreur, vous devez passer $DISPLAY and .X11-unix à docker, ainsi que de donner à l'utilisateur qui a commencé l'accès à docker à xhost.
dans docker-composer.yml:
version: '2'
services:
node:
build: .
container_name: node
environment:
- DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
Dans le terminal ou le script:
-
xhost +si:localuser:$USER
-
xhost +local:docker
-
export DISPLAY=$DISPLAY
-
docker-compose up
OSX (10.13.6, high sierra)
semblable à @Nick réponse de", mais sa solution n'a pas fonctionné pour moi.
installer d'abord socat en faisant brew install socat
, et installer XQuartz ( https://www.xquartz.org / )
a ensuite suivi ces étapes ici ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker / ) dans la section des commentaires:
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
j'ai aussi pu lancer CLion à partir de mon conteneur debian docker.