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?

309
demandé sur Peter Mortensen 2013-04-30 13:40:54

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
190
répondu creack 2018-07-24 10:01:13

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
159
répondu Jürgen Weigert 2014-08-13 07:40:53

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

51
répondu A. Binzxxxxxx 2018-06-07 12:52:25

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.

47
répondu Aryeh Leib Taurog 2014-09-11 15:20:30

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 .

24
répondu timthelion 2015-08-17 22:11:44

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:

  1. Xquartz (OSX n'est plus fourni avec X11 server)
  2. transfert de socket avec socat (brew install socat)
  3. 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:

  1. Installer MobaXterm pour windows
  2. Start MobaXterm
  3. Configurer le serveur X: Paramètres -> X11 (onglet) -> mettre X11 accès à distance à complet "1519380920
  4. 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

xeyes running on PC

19
répondu Nick 2017-05-23 12:10:33

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
17
répondu danidiaz 2014-06-30 19:51:13

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 ou xinput est possible, et la commande à distance des applications hôtes avec xdotool .
  • 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
11
répondu mviereck 2018-09-18 14:11:17

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.

10
répondu dashesy 2017-03-29 17:20:55

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 /

8
répondu Anshuman Manral 2017-09-13 14:53:55

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 .

6
répondu niutech 2017-05-23 12:10:33

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.

6
répondu Pithikos 2014-10-18 09:23:06

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.

4
répondu allenyllee 2017-11-11 12:54:15

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.

3
répondu Matt McCormick 2014-08-21 04:29:12

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:

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.

3
répondu Vince 2017-05-11 14:33:46

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

. 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 fichiers Xauthority 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.
3
répondu orodbhen 2018-08-15 12:41:55

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
2
répondu wedesoft 2016-08-11 10:00:57

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
1
répondu nathangeorge1 2018-05-18 17:55:35

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.

0
répondu nommer 2018-07-27 23:44:31