Comment pouvez-vous exécuter des applications GUI dans un conteneur Docker ?
Y a-t-il des images qui sont configurées vncserver
ou quelque chose pour que vous puissiez - par exemple - ajouter un sandbox speedbump supplémentaire autour de Firefox?
Comment pouvez-vous exécuter des applications GUI dans un conteneur Docker ?
Y a-t-il des images qui sont configurées vncserver
ou quelque chose pour que vous puissiez - par exemple - ajouter un sandbox speedbump supplémentaire autour de Firefox?
Réponses:
Vous pouvez simplement installer un serveur vnc avec Firefox :)
J'ai poussé une image, vnc / firefox, ici: docker pull creack/firefox-vnc
L'image a été réalisée 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 va créer 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
docker inspect <container id>
ou simplement docker ps
, puis vous vous connectez à l'IP de votre hôte avec le port que vous venez de trouver.
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 transmettre 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 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 n'ait pas d'importance. Nous devons définir la famille d'authentification sur «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 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
-v $XSOCK:$XSOCK -v $XAUTH:$XAUTH
peut être raccourci à-v $XSOCK -v $XAUTH
:0
par $DISPLAY
. Cela signifie xauth nlist $DISPLAY | ...
et docker run -ti -e DISPLAY=$DISPLAY ...
. Habituellement, le X DISPLAY l'est :0
, mais pas toujours (et surtout pas si vous vous connectez via ssh -X).
/tmp/.docker.xauth
fichier avec des 600
autorisations. Il en résulte que xauth dans le conteneur Docker ne peut pas lire le fichier. Vous pouvez vérifier en exécutant xauth list
dans le conteneur Docker. J'ai ajouté chmod 755 $XAUTH
après la xauth nlist :0 | ...
commande pour résoudre ce problème.
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 c'est si facile.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
AVANTAGES:
+ pas de serveur x dans le conteneur docker
+ pas de client / serveur vnc nécessaire
+ pas de ssh avec transfert x
+ conteneurs docker beaucoup plus petits
CONTRE:
- utilisation de x sur l'hôte (non destiné au 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/2835523
apt-get -y install sudo
pour créer un /etc/sudoers.d
dossier.
$ xhost +
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 Dockerfile comme celui-ci:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Vous pouvez effectuer les opérations suivantes:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
Bien sûr, cela est essentiellement le même que le transfert X. Il accorde au conteneur un accès complet au xserver sur l'hôte, il n'est donc recommandé que si vous faites confiance à ce qu'il contient.
Remarque: Si vous êtes préoccupé par la sécurité, une meilleure solution serait de confiner l'application avec un contrôle d'accès obligatoire ou basé sur les rôles. Docker atteint une assez bonne isolation, mais il a été conçu dans un but différent. Utilisez AppArmor , SELinux ou GrSecurity , qui ont été conçus pour répondre à votre préoccupation.
xhost +
sur l'hôte.
xhost +local
est nécessaire. Il serait cependant préférable de rendre le ~/.Xauthority
fichier disponible dans le conteneur, afin qu'il puisse s'authentifier.
Can't open display: :0
. Des idées?
xhost +si:localuser:$USER
J'autoriser que l'utilisateur à partir du conteneur.
Vous pouvez également utiliser un sous-utilisateur: https://github.com/timthelion/subuser
Cela vous permet de regrouper de nombreuses applications GUI dans Docker. Firefox et emacs ont été testés jusqu'à présent. Avec firefox, webGL ne fonctionne pas cependant. Le chrome ne fonctionne pas du tout.
EDIT: Le son fonctionne!
EDIT2: Depuis la première fois que j'ai posté ceci, le sous-utilisateur a beaucoup progressé. J'ai maintenant un site Web up subuser.org , et un nouveau modèle de sécurité pour se connecter à X11 via un pont XPRA .
Jürgen Weigert a la meilleure réponse qui a fonctionné pour moi sur Ubuntu, cependant sur OSX, docker s'exécute à l'intérieur de VirtualBox et donc la solution ne fonctionne pas sans plus de travail.
Je l'ai avec ces ingrédients supplémentaires:
J'apprécierais les commentaires des utilisateurs pour améliorer cette réponse pour OSX, je ne sais pas si le transfert de socket pour X est sécurisé, mais mon utilisation prévue est d'exécuter le conteneur Docker localement uniquement.
De plus, le script est un peu fragile en ce qu'il n'est pas facile d'obtenir l'adresse IP de la machine car elle se trouve sur notre réseau local sans fil, il s'agit donc 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 sur 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
error: XDG_RUNTIME_DIR not set in the environment.
et Error: cannot open display: VAIO:0.0
. Avez-vous rencontré quelque chose comme ça?
Partage de l'affichage de l'hôte: 0, comme indiqué dans certaines autres réponses, présente deux inconvénients:
xev
ou xinput
est possible, et le contrôle à distance des applications hôtes avec xdotool
.--ipc=host
).Ci-dessous un exemple de script pour exécuter une image docker dans Xephyr qui résout ce problème.
--cap-drop ALL --security-opt no-new-privileges
. L'utilisateur du conteneur n'est pas non plus root.Le script attend certains arguments, d'abord un gestionnaire de fenêtres hôtes à exécuter dans Xephyr, deuxièmement une image docker, éventuellement une troisième commande image à exécuter. Pour exécuter un environnement de bureau dans Docker, utilisez ":" au lieu d'un gestionnaire de fenêtres hôte.
La fermeture de la fenêtre Xephyr met fin aux applications de 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 sur le wiki x11docker . Un script plus avancé est x11docker qui prend également en charge des fonctionnalités telles que l'accélération GPU, le partage de webcam et d'imprimante, etc.
Voici une solution légère qui évite d'avoir à installer n'importe quel X
serveur, vnc
serveur ou sshd
démon sur le conteneur. Ce qu'il gagne en simplicité, il le perd en sécurité et en isolement.
Il suppose que vous vous connectez à la machine hôte à l'aide ssh
de la X11
redirection.
Dans la sshd
configuration de l'hôte, ajoutez la ligne
X11UseLocalhost no
Alors que le port du 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 exécuté, doit avoir accès au .Xauthority
fichier pour pouvoir se connecter au serveur. Pour ce faire, nous définissons un volume en lecture seule pointant vers le répertoire personnel de l'hôte (ce n'est peut-être pas une bonne idée!) Et définissons également la XAUTHORITY
variable 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):/")
On peut 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
.Xauthority
fichier lui - même: -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
.
X11UseLocalhost
, vous pouvez également utiliser l'option supplémentaire --net=host
pour la docker run
commande (trouvée ici ).
--net=host
est une mauvaise idée car maintenant si vous ouvrez un port dans le conteneur, il sera également ouvert dans l'hôte ...
Bien que la réponse de Jürgen Weigert couvre essentiellement cette solution, je ne savais pas au début ce qui était décrit ici. Je vais donc ajouter mon point de vue, au cas où quelqu'un d'autre aurait besoin de clarifications.
Tout d' abord, la documentation pertinente est la page de manuel de sécurité X .
De nombreuses sources en ligne suggèrent simplement de monter le socket Unix X11 et le ~/.Xauthority
fichier dans le conteneur. Ces solutions fonctionnent souvent par chance, sans vraiment comprendre pourquoi, par exemple, l'utilisateur du conteneur se retrouve avec le même UID que l'utilisateur, il n'y a donc pas besoin d'autorisation de clé magique.
Tout d'abord, le fichier Xauthority a le mode 0600, donc l'utilisateur du conteneur ne pourra le lire que s'il a le même UID.
Même si vous copiez le fichier dans le conteneur et changez de 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 Xauthority
fichier, vous verrez différentes entrées 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, il ne voit pas le cookie magique pour la session X en cours d'exécution 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ées ci-dessous).
Donc, 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'est-à-dire la session X en cours d'exécution sur votre bureau), par exemple:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
Le hic, c'est que le cookie doit être ajouté à l' xauth add
intérieur du conteneur:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Sinon, xauth
marquez-le de manière à ce qu'il ne soit visible qu'à l'extérieur du conteneur.
Le format de cette commande est:
xauth add hostname/$DISPLAY protocol hexkey
Où .
représente le MIT-MAGIC-COOKIE-1
protocole.
Remarque: il n'est pas nécessaire de copier ou de monter-lier .Xauthority
dans le conteneur. Créez simplement un fichier vierge, comme indiqué, et ajoutez le cookie.
La réponse de Jürgen Weigert contourne ce problème en utilisant le FamilyWild
type de connexion 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é hexadécimale de la session X en cours d' ~/.Xauthority
utilisation xauth nlist
.
Les étapes essentielles sont donc:
FamilyWild
type de connexion).J'avoue que je ne comprends pas très bien comment FamilyWild
fonctionne, ou comment xauth
ou les clients X filtrent les entrées du fichier Xauthority en fonction de l'endroit où elles sont exécutées. Des informations supplémentaires à ce sujet sont les bienvenues.
Si vous souhaitez distribuer votre application Docker, vous aurez besoin d'un script de démarrage pour exécuter le conteneur qui obtient la clé hexadécimale 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.
Il permet également de comprendre les mécanismes du processus d'autorisation:
$DISPLAY
./tmp/.X11-unix
répertoire monté dans le conteneur.Remarque: Le socket Unix X11 doit toujours être monté dans le conteneur, sinon le conteneur n'aura aucun itinéraire vers le serveur X. La plupart des distributions désactivent par défaut l'accès TCP au serveur X 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 de consulter l'exemple de transfert SSH X:
$DISPLAY
dans la session SSH pour pointer vers son propre serveur X.xauth
pour créer un nouveau cookie pour l'hôte distant et l'ajoute aux Xauthority
fichiers pour les utilisateurs locaux et distants.Ce n'est pas léger mais c'est une bonne solution qui donne la parité des fonctionnalités de docker avec la virtualisation complète du bureau. Les deux Xfce4 ou IceWM pour Ubuntu et CentOS fonctionnent, et l' noVNC
option permet un accès facile via un navigateur.
https://github.com/ConSol/docker-headless-vnc-container
Il fonctionne noVNC
aussi bien que tigerVNC
vncserver. Ensuite, il demande startx
un gestionnaire de fenêtres donné. En outre, libnss_wrapper.so
est utilisé pour émuler la gestion des mots de passe pour les utilisateurs.
xpra
docker, qui est sans racine X. xpra
était l'OMI le mieux adapté et est plus efficace que VNC.
--device /dev/...
au docker et définissez les --cap
privilèges nécessaires . Cela va à l'encontre de l'objectif de confinement, mais vous pouvez passer à travers des appareils. Avec quelques ajustements, il devrait être possible, je crois, d'exécuter GNOME / KDE sous VNC. J'ai exécuté plusieurs X dans docker avec des cartes nvidia (pas de VNC ou Xpra), donc c'est certainement faisable.
La solution proposée sur http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ semble être un moyen facile de démarrer des applications GUI à l'intérieur des conteneurs (j'ai essayé pour firefox par rapport à Ubuntu 14.04) mais j'ai trouvé qu'un petit changement supplémentaire est nécessaire à la solution posté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) que 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 docker avec les informations sur cette page et ces conclusions supplémentaires: https://hub.docker.com/r/amanral/ubuntu-firefox/
/tmp/.X11-unix
tout. Cela fonctionne juste avec le montage .Xauthority
et --net=host
.
/tmp/.X11-unix
as volume ne fonctionne plus, car docker refuse silencieusement les montages de volume à partir de répertoires collants.
--network=host
passe. Il donne à votre conteneur un accès complet à la pile réseau de l'hôte, ce qui peut être indésirable, selon ce que vous essayez de faire. Si vous essayez simplement d'exécuter des GUI conteneurisées sur votre bureau, cela ne devrait pas avoir d'importance.
Il y a une autre solution par lord.garbage pour exécuter des applications GUI dans un conteneur sans utiliser le transfert VNC, SSH et X11. Il est également mentionné ici .
Si vous souhaitez exécuter une application GUI sans tête, lisez ici . Ce que vous devez faire est de créer un moniteur virtuel avec xvfb
ou tout autre logiciel similaire. Ceci est très utile si vous souhaitez exécuter des tests Selenium par exemple avec des navigateurs.
Quelque chose qui n'est mentionné nulle part est que certains logiciels utilisent eux-mêmes le bac à sable 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.
Je suis en retard à la fête, mais pour les utilisateurs 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 en utilisant l'application de 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 fichier Lisezmoi lié pour les commandes de génération et d'exécution si vous le souhaitez / avez besoin.
Sur la base de la réponse de Jürgen Weigert , j'ai une 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 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
Au redémarrage du système, avant la connexion de l'utilisateur, docker montera 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, puis 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 connexion de l'utilisateur.
Les autres solutions devraient fonctionner, mais voici une solution pour docker-compose
.
Pour corriger cette erreur, vous devez transmettre $ DISPLAY et .X11-unix à docker, ainsi qu'accorder à l'utilisateur qui a démarré docker l'accès à xhost.
Dans le docker-compose.yml
fichier:
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
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.
Semblable à la réponse de @Nick , mais sa solution n'a pas fonctionné pour moi.
Installez d'abord socat en faisant brew install socat
, et 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 Docker Debian.
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 des autorisations plus privées
xhost +
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name
Encore une autre réponse au cas où vous auriez déjà construit l'image:
invoquer le docker sans sudo ( Comment réparer le docker: problème de permission refusée )
partager le même UTILISATEUR & home & passwd entre l'hôte et le partage de conteneur (astuces: utiliser l'ID utilisateur au lieu du nom d'utilisateur)
le dossier de développement pour que les bibliothèques dépendantes du pilote fonctionnent correctement
plus X11 vers l'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 l'intérêt d'utiliser docker si tant de choses sont les mêmes? eh bien, une raison pour laquelle je peux penser est de surmonter l'enfer de la dépendance des packages ( https://en.wikipedia.org/wiki/Dependency_hell ).
Donc ce type d'utilisation est plus adapté au développeur je pense.
echo ~
: / home / $ {USER} --user = id -u ${USER}
--env = "DISPLAY" --volume = "/ etc / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
J'ai réussi à exécuter un flux vidéo à partir d'une caméra USB à l'aide opencv
de docker
en suivant ces étapes:
Laissez Docker accéder au serveur X
xhost +local:docker
Créez le socket Unix X11 et le fichier d'authentification X
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
Ajouter les autorisations appropriées
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
Réglez la vitesse de rendu Qt sur "native" pour qu'elle ne contourne pas le moteur de rendu X11
export QT_GRAPHICSSYSTEM=native
Dites à Qt de ne pas utiliser MIT-SHM (mémoire partagée) - de cette façon, cela devrait également être plus sûr en termes de sécurité
export QT_X11_NO_MITSHM=1
Mettre à jour la commande docker run
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
Remarque: Lorsque vous avez terminé le projet, remettez les contrôles d'accès à leur valeur par défaut - xhost -local:docker
Plus de détails: utilisation des interfaces graphiques avec Docker
Crédit: Détection d'objets en temps réel et de traitement vidéo à l'aide de Tensorflow, OpenCV et Docker