Comment exécuter des applications graphiques dans un conteneur Docker ?
Existe-t-il des images qui configurent vncserver
ou quelque chose qui vous permette, par exemple, d'ajouter un sandbox Speedbump supplémentaire autour de Firefox?
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é faite avec ce 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 exécutant VNC avec le mot de passe 1234
:
Pour Docker version 18 ou plus récente:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
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 supprimer toute protection avec xhost + avant d'exécuter mes conteneurs Docker, soit transférer 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 à celui du système hôte n'a pas aidé dans mon cas. xeyes (j'aime cet exemple) ignorerait simplement le cookie magique et ne transmettrait aucune information d'identification au serveur. Par conséquent, nous obtenons un message d'erreur "Aucun protocole spécifié. Impossible d'ouvrir l'affichage"
Le fichier Xauthority peut être écrit de manière à ce que le nom d’hôte ne soit pas important. Nous devons définir la famille d'authentification sur 'FamilyWild'. Je ne sais pas si xauth a une ligne de commande appropriée pour cela, voici donc 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 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 souhaite la partager ici avec vous car je pense que c'est la meilleure façon de le faire et que c'est si facile.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
AVANTAGES:
+ pas de serveur dans le conteneur de menu fixe
+ aucun client/serveur vnc nécessaire
+ pas de ssh avec x forwarding
+ dockers beaucoup plus petits
LES INCONVÉNIENTS:
- utilisation de x sur l'hôte (non conçu pour le sandbox sécurisé)
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 également le faire dans la commande d'exécution avec sh -c "echo script-here"
CONSEIL: pour l'audio, consultez: https://stackoverflow.com/a/28985715/283552
Avec les volumes de données Docker, il est très facile d'exposer le socket de domaine unix de xorg à l'intérieur du conteneur.
Par exemple, avec un fichier Dockerfile comme ceci:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Vous pouvez 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 identique à la transmission X. Il accorde au conteneur un accès complet au serveur x sur l'hôte. Il est donc recommandé de ne le faire que si vous avez confiance en ce qu'il contient.
Remarque: Si la sécurité vous préoccupe, une meilleure solution consisterait à limiter l'application à obligatoire - ou basé sur les rôles - contrôle d'accès. Docker réalise un assez bon isolement, mais il a été conçu dans un but différent. Utilisez AppArmor , SELinux ou GrSecurity , conçus pour répondre à votre préoccupation.
Vous pouvez également utiliser le sous-utilisateur: https://github.com/timthelion/subuser
Cela vous permet de conditionner de nombreuses applications graphiques dans docker. Firefox et Emacs ont été testés jusqu'à présent. Avec Firefox, WebGL ne fonctionne pas bien. Le chrome ne fonctionne pas du tout.
EDIT: Le son fonctionne!
EDIT2: Depuis que j'ai posté ceci, le sous-utilisateur a beaucoup progressé. J'ai maintenant un site Web en construction subuser.org et un nouveau modèle de sécurité pour la connexion à X11 via le pontage XPRA .
Jürgen Weigert a la meilleure réponse qui ait fonctionné pour moi sous Ubuntu, mais sous OSX, docker fonctionne dans VirtualBox et la solution ne fonctionne donc pas sans travail supplémentaire.
Je l'ai travailler avec ces ingrédients supplémentaires:
J'apprécierais les commentaires des utilisateurs pour améliorer cette réponse sous OSX. Je ne sais pas si le transfert de socket pour X est sécurisé, mais mon utilisation prévue est de n'exécuter que le conteneur de menu fixe en local.
En outre, le script est un peu fragile en ce sens qu'il n'est pas facile d'obtenir l'adresse IP de la machine car celle-ci se trouve sur notre réseau local sans fil, donc il s'agit toujours d'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 $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
Je suis capable de faire fonctionner xeyes et matplotlib avec cette approche.
C'est un peu plus facile avec Windows 7+ avec 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
Voici une solution légère qui évite de devoir installer un serveur X
, vnc
ou un démon sshd
sur le conteneur. Ce qu’il gagne en simplicité, il perd en sécurité et en isolement.
Cela suppose que vous vous connectiez à la machine hôte à l'aide de ssh
avec le transfert de X11
.
Dans la configuration sshd
de l'hôte, ajoutez la ligne
X11UseLocalhost no
Ainsi, le port de serveur X transféré 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 exécuté, doit accéder au fichier .Xauthority
afin de pouvoir se connecter au serveur. Pour ce faire, nous définissons un volume en lecture seule pointant vers le répertoire de base de l'hôte (ce n'est peut-être pas une bonne idée!) Et définissons également la variable XAUTHORITY
en conséquence.
docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
Cela ne suffit pas, nous devons également passer la variable DISPLAY 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 testez-le comme ceci:
dockerX11run centos xeyes
L'affichage de l'hôte de partage: 0, comme indiqué dans d'autres réponses, présente deux inconvénients:
xev
ou xinput
est possible, et le contrôle à distance d'applications hôtes avec xdotool
.--ipc=Host
).Ci-dessous, un exemple de script pour exécuter une image de menu fixe dans Xephyr qui résout ce problème.
--cap-drop ALL --security-opt no-new-privileges
. De plus, l'utilisateur du conteneur est et non root.Le script attend quelques arguments, tout d'abord un gestionnaire de fenêtres hôte à exécuter dans Xephyr, deuxièmement une image de menu fixe, éventuellement une troisième commande d'image à exécuter. Pour exécuter un environnement de bureau dans docker, utilisez ":" à la place d'un gestionnaire de fenêtres hôte.
La fermeture de la fenêtre Xephyr met fin aux applications du conteneur Docker. La fermeture des applications ancrées 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
Script 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
Ce script est maintenu à x11docker wiki . x11docker est un script plus avancé qui prend également en charge des fonctionnalités telles que l’accélération GPU, le partage de la webcam et des imprimantes, etc.
Ce n'est pas léger mais c'est une solution Nice qui donne la parité des fonctionnalités de docker avec la virtualisation complète du bureau. Xfce4 ou IceWM pour Ubuntu et CentOS fonctionnent tous deux, et l’option noVNC
facilite l’accès via un navigateur.
https://github.com/ConSol/docker-headless-vnc-container
Il exécute noVNC
ainsi que le vncserver de tigerVNC
. Ensuite, il appelle startx
pour un gestionnaire de fenêtres donné. De plus, libnss_wrapper.so
est utilisé pour émuler la gestion des mots de passe pour les utilisateurs.
Alors que la réponse de Jürgen Weigert couvre essentiellement cette solution, je ne comprenais pas tout d'abord ce qui était décrit ici. J'ajouterai donc mon point de vue, au cas où quelqu'un aurait besoin de clarification.
Tout d’abord, la documentation pertinente est la page de sécurité X .
De nombreuses sources en ligne suggèrent simplement de monter le socket X11 Unix et le fichier ~/.Xauthority
dans le conteneur. Ces solutions fonctionnent souvent par hasard, sans vraiment comprendre pourquoi, par ex. l'utilisateur du conteneur se retrouve avec le même UID que l'utilisateur, il n'est donc pas nécessaire d'autoriser une clé magique.
Tout d'abord, le fichier Xauthority a le mode 0600, de sorte que l'utilisateur du conteneur ne sera pas en mesure de le lire à moins qu'il ait le même UID.
Même si vous copiez le fichier dans le conteneur et changez le propriétaire, 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
, différentes entrées seront répertoriées. En effet, xauth
filtre les entrées en fonction de l'endroit où elles sont exécutées.
Le client X dans le conteneur (c'est-à-dire l'application GUI) se comportera de la même manière que xauth
. En d'autres termes, le cookie magique de la session X ne s'exécute pas sur le bureau de l'utilisateur. Au lieu de cela, il voit les entrées de toutes les sessions X "distantes" que vous avez précédemment ouvertes (expliquées ci-dessous).
Vous devez donc ajouter une nouvelle entrée avec le nom d’hôte du conteneur et la même clé hexagonale que le cookie hôte (c’est-à-dire la session X exécutée sur votre bureau), par exemple:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
Le problème, c'est que le cookie doit être ajouté avec xauth add
à l'intérieur du conteneur:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Sinon, xauth
le marque de telle sorte qu'il ne soit visible que hors du conteneur.
Le format de cette commande est:
xauth add hostname/$DISPLAY protocol hexkey
Où .
représente le protocole MIT-MAGIC-COOKIE-1
.
Remarque: Il n'est pas nécessaire de copier ou de lier-monter .Xauthority
dans le conteneur. Créez simplement un fichier vide, comme indiqué, et ajoutez le cookie.
--- La réponse de Jürgen Weigert résout ce problème en utilisant le type de connexion FamilyWild
pour créer un nouveau fichier d'autorité sur l'hôte et le copier dans le conteneur. Notez qu'il extrait d'abord la clé hexagonale de la session X actuelle de ~/.Xauthority
à l'aide de xauth nlist
.
Les étapes essentielles sont donc:
FamilyWild
.).J'admets que je ne comprends pas très bien comment fonctionne FamilyWild
, ni comment les clients xauth
ou X filtrent les entrées du fichier Xauthority en fonction de leur emplacement. Des informations supplémentaires à ce sujet sont les bienvenues.
Si vous souhaitez distribuer votre application Docker, vous avez besoin d'un script de démarrage pour exécuter le conteneur qui obtient la clé hexagonale de la session X de l'utilisateur et l'importe dans le conteneur de l'une des deux manières expliquées précédemment.
Cela aide également à comprendre les mécanismes du processus d'autorisation:
$DISPLAY
./tmp/.X11-unix
monté dans le conteneur.Remarque: Le socket Unix X11 doit toujours être monté dans le conteneur, sinon le conteneur n'aura aucune route vers le serveur X. La plupart des distributions désactivent TCP l'accès au serveur X par défaut pour des raisons de sécurité.
Pour plus d'informations et pour mieux comprendre le fonctionnement de la relation client/serveur X, il est également utile d'examiner le cas de transfert X SSH:
$DISPLAY
dans la session SSH pour qu'elle pointe vers son propre serveur X.xauth
pour créer un nouveau cookie pour l'hôte distant et l'ajoute aux fichiers Xauthority
des utilisateurs locaux et distants.La solution proposée sur http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ semble être un moyen simple de lancer des applications à interface graphique de l'intérieur. les 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 publiée par l'auteur.
Plus précisément, pour l’exécution du 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 (sur la base d’un commentaire particulier sur le même site) deux options supplémentaires
-v $HOME/.Xauthority:$HOME/.Xauthority
et
-net=Host
doivent être spécifiés lors de l’exécution 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 de menu fixe avec les informations sur cette page et ces découvertes supplémentaires: https://hub.docker.com/r/amanral/ubuntu-firefox/
Il existe ne autre solution proposée par lord.garbage pour exécuter des applications à interface graphique dans un conteneur sans utiliser le transfert VNC, SSH et X11. Il est mentionné ici aussi.
Si vous voulez exécuter une application graphique sans tête, lisez 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 souhaitez exécuter des tests Selenium, par exemple avec des navigateurs.
Quelque chose n'est mentionné nulle part, c'est que certains logiciels utilisent eux-mêmes le sand-boxing avec des conteneurs Linux. Ainsi, par exemple, Chrome ne fonctionnera jamais normalement si vous n'utilisez pas l'indicateur approprié --privileged
lors de l'exécution du conteneur.
Basé sur la réponse de Jürgen Weigert , j'ai quelques améliorations:
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 sert à 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 consiste à créer un dossier vide nommé $ XAUTH_DIR dans/tmp et à changer son mode en 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
Lorsque le système redémarre, avant la connexion de l'utilisateur, docker monte automatiquement le répertoire $ XAUTH_DIR si la stratégie de redémarrage du conteneur est "toujours". Après la connexion de l'utilisateur, vous pouvez écrire une commande dans ~/.profile qui consiste à créer le fichier $ XAUTH. Le conteneur utilisera automatiquement ce fichier $ 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
Après tout, le conteneur obtiendra automatiquement le fichier Xauthority à chaque redémarrage du système et à la connexion de l'utilisateur.
Je suis en retard pour la fête, mais pour les utilisateurs de Mac qui ne veulent pas emprunter le chemin XQuartz, voici un exemple de travail qui construit une image Fedora avec un environnement de bureau (xfce) en utilisant Xvfb
et VNC
. C'est simple et ça marche:
Sur un Mac, vous pouvez simplement y accéder à l'aide de l'application Partage d'écran (par défaut), en vous 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
Vérifiez le lié readme pour construire et exécuter des commandes si vous voulez/avez besoin.
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 l'hôte.
Vous pouvez autoriser l’utilisateur 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 transmettre $ DISPLAY et .X11-unix au menu fixe, ainsi que donner à l'utilisateur qui a lancé le menu fixe l'accès à xhost.
Dans le fichier docker-compose.yml
:
version: '2'
services:
node:
build: .
container_name: node
environment:
- DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
En terminal ou en script:
xhost +si:localuser:$USER
xhost +local:docker
export DISPLAY=$DISPLAY
docker-compose up
Encore une autre réponse au cas où vous avez déjà construit l'image:
invoquer le docker sans Sudo ( Comment résoudre le docker: problème d'autorisation refusée )
partager le même USER & home & passwd entre l'hôte et le partage de conteneur (astuces: utilisez l'ID utilisateur au lieu du nom d'utilisateur)
le dossier dev pour que les bibliothèques dépendantes du pilote fonctionnent bien
plus X11 en avant.
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
vous pouvez demander, quel est le point d'utiliser docker si tant de choses sont les mêmes? Eh bien, une raison à laquelle je peux penser est de surmonter l'enfer de la dépendance du paquet ( https://en.wikipedia.org/wiki/Dependency_hell ).
Donc, ce type d'utilisation est plus approprié pour le développeur, je pense.
Similaire à la réponse de @ Nick , mais sa solution n'a pas fonctionné pour moi.
Commencez par installer socat en faisant brew install socat
, puis installez XQuartz ( https://www.xquartz.org/ )
Ensuite, suivez 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 également pu lancer CLion à partir de mon conteneur Debian Docker.
Docker avec réseau BRIDGE. pour Ubuntu 16.04 avec le gestionnaire d'affichage lightdm:
cd /etc/lightdm/lightdm.conf.d
Sudo nano user.conf
[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp
vous pouvez utiliser plus d'autorisations privées
xhost +
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$Host_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name