Pouvez-vous exécuter des applications graphiques dans un conteneur Docker?

Comment pouvez-vous exécuter des applications graphiques dans un conteneur Docker ?

Existe-t-il des images qui configurent vncserver ou quelque chose de ce vncserver afin que vous puissiez, par exemple, append un sandbox de speedbump supplémentaire, par exemple 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 fichier Docker:

     # 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 sortingck) RUN bash -c 'echo "firefox" >> /.bashrc' 

    Cela créera un conteneur Docker exécutant VNC avec le mot de passe 1234 :

    Pour Docker version 1.3 ou ultérieure:

     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 ignorer 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 à l’hôte. Avec docker, chaque conteneur peut avoir un nom d’hôte différent (défini avec docker run -h), mais même la définition du 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. Nous obtenons donc un message d’erreur “Aucun protocole spécifié” Impossible d’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 sur «FamilyWild». Je ne suis pas sûr, 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 veux la partager ici avec vous car je pense que c’est la meilleure façon de le faire et que c’est si simple.

    http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/

    AVANTAGES:
    + pas de trucs de serveur x dans le conteneur de docker
    + aucun client / serveur vnc requirejs
    + pas de ssh avec x forwarding
    + des conteneurs docker beaucoup plus petits

    LES INCONVÉNIENTS:
    – utiliser x sur l’hôte (non destiné au sandboxing 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 aussi le faire dans la commande run avec sh -c "echo script-here"

    ASTUCE: pour l’audio, consultez: https://stackoverflow.com/a/28985715/2835523

    Avec les volumes de données de 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 Docker comme celui-ci:

     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 le même que X-forwarding. Il accorde au conteneur un access complet au serveur x sur l'hôte, il est donc recommandé de ne faire confiance qu'à ce qui est à l'intérieur.

    Remarque: Si vous êtes concerné par la sécurité, une meilleure solution consisterait à confiner l'application avec un contrôle d'access obligatoire ou basé sur les rôles. Docker obtient un très bon isolement, mais il a été conçu avec un objective différent. Utilisez AppArmor , SELinux ou GrSecurity , conçus pour répondre à vos préoccupations.

    Vous pouvez également utiliser le sous-utilisateur: https://github.com/timthelion/subuser

    Cela vous permet de regrouper de nombreuses applications d’interface graphique 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 sur subuser.org , et un nouveau modèle de sécurité pour la connexion à X11 via le pontage XPRA .

    OSX

    Jürgen Weigert a la meilleure réponse qui a fonctionné pour moi sur Ubuntu, cependant sur OSX, Docker s’exécute dans VirtualBox et la solution ne fonctionne pas sans plus de travail.

    Je travaille avec ces ingrédients supplémentaires:

    1. Xquartz (OSX n’est plus livré avec le serveur X11)
    2. transfert de socket avec socat (srew installation de armsage)
    3. script bash 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 le transfert de socket pour X est sécurisé, mais mon utilisation est prévue pour exécuter le conteneur docker uniquement localement.

    En outre, le script est un peu fragile car il n’est pas facile d’obtenir l’adresse IP de la machine car elle se trouve sur notre réseau local sans fil.

    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 peux utiliser xeyes et matplotlib avec cette approche.

    Windows 7+

    C’est un peu plus facile sur Windows 7+ avec MobaXterm:

    1. Installez MobaXterm pour Windows
    2. Démarrer MobaXterm
    3. Configurer le serveur X: Paramètres -> X11 (onglet) -> définir l’ access à distance à X11
    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 en cours d'exécution sur PC

    Voici une solution légère qui évite d’avoir à installer un serveur X , vnc serveur vnc ou un démon sshd sur le conteneur. Ce qu’il gagne en simplicité, il perd en sécurité et en isolation.

    Il suppose que vous vous connectez à l’ordinateur hôte à l’aide de ssh avec le transfert X11 .

    Dans la configuration sshd de l’hôte, ajoutez la ligne

     X11UseLocalhost no 

    Pour que le port du serveur X transféré sur l’hôte soit ouvert sur toutes les interfaces (pas seulement lo ) et en particulier sur l’interface virtuelle Docker, docker0 .

    Lorsqu’il est exécuté, le conteneur doit avoir access 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 de base sur l’hôte (peut-être pas une idée judicieuse!) Et définissons également la variable XAUTHORITY 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 

    Partage de l’affichage de l’hôte: 0, comme indiqué dans d’autres réponses, présente deux inconvénients:

    • Il brise l’isolation du conteneur en raison de certaines fuites de sécurité X. Par exemple, le keylogging avec xev ou xinput est possible.
    • Les applications peuvent avoir des problèmes de rendu et des erreurs d’access à la mémoire RAM en raison de l’absence de mémoire partagée pour l’extension X MIT-SHM.

    Pour contourner les fuites de sécurité X et éviter le problème MIT-SHM, j’ai publié x11docker sur github . L’idée principale est d’exécuter un second serveur X avec ses propres cookies d’authentification et avec MIT-SHM désactivé. Les conteneurs docker ont access au nouveau serveur X et sont séparés de l’affichage hôte: 0. Il n’y a pas de dépendances X dans l’image car X / Xephyr est fourni par l’hôte.

    Ci-dessous un exemple de script pour exécuter une image de docker dans Xephyr. Il attend quelques arguments, d’abord un gestionnaire de fenêtres hôte à exécuter dans Xephyr, ensuite une image de docker, éventuellement une troisième commande d’image à exécuter. Pour exécuter un environnement de bureau dans docker, utilisez “:” au lieu d’un gestionnaire de fenêtres hôte. Sur les systèmes sans mot de passe root, modifiez la variable $Getroot

    Xephyr commence à utiliser xinit. Un xinitrc personnalisé est créé pour créer un cookie, définir la disposition du clavier, exécuter le gestionnaire de fenêtres et exécuter xterm avec xtermrc pour demander un mot de passe pour exécuter docker.

    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.

    Annotations:

    • Le problème MIT-SHM peut également être évité avec l’option docker --ipc=host , mais cela désactive l’isolation du conteneur et est déconseillé.
    • Le cookie doit être remplacé par “familiy wild” comme décrit par @ Jürgen Weigert si un socket X partagé est utilisé. Avec X sur TCP, ce n’est pas nécessaire.
    • des solutions similaires sont possibles avec Xpra, Xorg et Xvnc
    • Pour X sur tcp, recherchez ip du démon docker (principalement 172.17.42.1), partagez DISPLAY = 172.17.42.1: 1, créez un cookie pour lui, ne partagez pas NewXsocket et n’utilisez pas l’option -nolisten tcp de X / Xephyr. En utilisant X sur TCP, MIT-SHM est désactivé automatiquement.

    Exemples:

    • x11docker_example "openbox --sm-disable" x11docker/lxde pcmanfm
    • x11docker_example : x11docker/lxde

    script x11docker_example:

     #! /bin/bash # x11docker_example : Example script to run docker GUI applications in Xephyr. # Look at x11docker on github: https://github.com/mviereck/x11docker # # Usage: # x11docker_example WINDOWMANAGER DOCKERIMAGE [IMAGECOMMAND [ARGS]] # # WINDOWMANAGER host window manager for use with single GUI applications. # To run a desktop environment in docker, use ":" # DOCKERIMAGE docker image containing GUI applications or a desktop # IMAGECOMMAND command to run in image # Windowmanager="$1" && shift Dockerimage="$*" # command to get root permissions to run docker Getroot="su -c" # Getroot="sudo su -c" # Use this on systems without a root password like Ubuntu or Sparky # define new display and its X socket. Newdisplay=:1 # To make sure $Newdisplay is not already in use, check /tmp/.Xn-lock [ -e "/tmp/.X1-lock" ] && echo "Error: Display :1 is already in use" >&2 && exit 1 NewXsocket=/tmp/.X11-unix/X1 # cache folder and files Cachefolder=/tmp/x11docker_example mkdir -p $Cachefolder Xclientcookie=$Cachefolder/Xcookie.client Xservercookie=$Cachefolder/Xcookie.server Xtermrc=$Cachefolder/xtermrc Xinitrc=$Cachefolder/xinitrc Dockerpidfile=$Cachefolder/docker.pid Dockerlogfile=$Cachefolder/docker.log # 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 Dockercommand="docker run --rm -e DISPLAY=$Newdisplay -e XAUTHORITY=/Xcookie -v $Xclientcookie:/Xcookie:ro -v $NewXsocket:$NewXsocket:ro $Dockerimage" # command to run X/Xephyr # /usr/bin/Xephyr an absolute path to X server executable must be given # $Newdisplay 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 # -nolisten tcp disable tcp connections for security reasons # -extension MIT-SHM disable MIT-SHM to avoid rendering glitches and bad RAM access (+ instead of - enables it) # -retro nice retro look Xcommand="/usr/bin/Xephyr $Newdisplay -auth $Xservercookie -nolisten tcp -extension MIT-SHM -retro" # create xinitrc { echo "#! /bin/bash" echo "# set environment variables to new display and new cookie" echo "export DISPLAY=$Newdisplay" echo "export XAUTHORITY=$Xclientcookie" echo "# same keyboard layout as on host" echo "echo '$(setxkbmap -display $DISPLAY -print)' | xkbcomp - $Newdisplay" echo "# create new XAUTHORITY cookie file" echo ":> $Xclientcookie" echo "xauth generate $Newdisplay . untrusted" echo "cp $Xclientcookie $Xservercookie" 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 '"$Newdisplay | sed -e 's/^..../ffff/')" echo 'echo $Cookie | xauth -f '$Xclientcookie' nmerge -' 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 "# prompt for password" echo "xterm -title x11docker_example -e '/bin/bash $Xtermrc'" echo "# wait for docker to finish" echo 'Dockerpid=$(cat '$Dockerpidfile') && {' echo ' while [ -n "$(pgrep docker | grep $Dockerpid)" ] ; do' echo ' sleep 1' echo ' done }' [ "$Windowmanager" = ":" ] || echo 'kill $Windowmanagerpid' echo 'kill $Tailpid' } > $Xinitrc # create xtermrc for a password prompt { echo "#! /bin/bash" echo "echo 'x11docker_example will start docker on display $Newdisplay with command:'" echo "echo $Getroot '$Dockercommand'" echo "echo 'Please type in your password to run docker:'" echo "$Getroot 'nohup $Dockercommand 2>&1 1>$Dockerlogfile & echo "'$!'" > $Dockerpidfile'" } > $Xtermrc xinit $Xinitrc -- $Xcommand rm -Rf $Cachefolder 

    Ce n’est pas léger mais c’est une solution intéressante 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’access via un navigateur.

    https://github.com/ConSol/docker-headless-vnc-container

    Il exécute noVNC ainsi que le tigerVNC de tigerVNC. Ensuite, il appelle startx pour le gestionnaire de fenêtres donné. En outre, libnss_wrapper.so est utilisé pour émuler la gestion des mots de passe pour les utilisateurs.

    La solution proposée à l’ adresse http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ semble être un moyen simple de démarrer des applications graphiques depuis l’intérieur des conteneurs (j’ai essayé avec Firefox. sur Ubuntu 14.04) mais j’ai trouvé qu’un petit changement supplémentaire est nécessaire pour la solution publiée par l’auteur.

    Spécifiquement, pour exécuter 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 (basé sur un commentaire particulier sur le même site) deux options supplémentaires

      -v $HOME/.Xauthority:$HOME/.Xauthority 

    et

      -net=host 

    doit être spécifié 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 docker avec les informations sur cette page et ces résultats supplémentaires: https://hub.docker.com/r/amanral/ubuntu-firefox/

    Lord.garbage propose une autre solution pour exécuter des applications GUI dans un conteneur sans utiliser le transfert VNC, SSH et X11. C’est mentionné ici aussi.

    Si vous souhaitez exécuter une application graphique sans interface, lisez-la ici . Vous devez 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 avec des navigateurs par exemple.

    Quelque chose n’est pas mentionné quelque 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 le drapeau approprié – --privileged lors de l’exécution du conteneur.

    Sur la base de 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 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 pour créer un dossier vide nommé $ XAUTH_DIR dans / tmp et changer son mode sur 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 pour 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 recevra 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 l’hôte.

    Je suis en retard à la fête, mais pour les utilisateurs de Mac qui ne veulent pas passer par le chemin XQuartz, voici un exemple de travail qui génère une image Fedora, avec un environnement de bureau (xfce) utilisant Xvfb et VNC . C’est simple et fonctionne:

    Sur un Mac, vous pouvez simplement y accéder à l’aide de 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 readme lié pour les commandes build et run si vous voulez / avez besoin.

    Vous pouvez autoriser l’utilisateur Docker (ici: root) à accéder à l’écran 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 

    Alors que la réponse de Jürgen Weigert couvre essentiellement cette solution, je ne voyais pas d’abord ce qui était décrit ici. Je vais donc append mon sharepoint vue, au cas où quelqu’un aurait besoin de clarification.

    Tout d’abord, la documentation pertinente est la page de manuel de sécurité X.

    De nombreuses sources en ligne suggèrent de monter le socket unix X11 et le fichier ~/.Xauthority dans le conteneur. Ces solutions fonctionnent souvent par hasard, sans vraiment comprendre pourquoi, par exemple, l’utilisateur du conteneur se retrouve avec le même UID que l’utilisateur, il n’est donc pas nécessaire d’obtenir une autorisation de 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 ait le même UID.

    Même si vous copiez le fichier dans le conteneur et modifiez la propriété, il y a encore un autre problème. Si vous exécutez la xauth list sur l’hôte et le conteneur, avec le même fichier Xauthority , vous verrez différentes entrées répertoriées. C’est parce que xauth filtre les entrées en fonction de l’endroit où il est exécuté.

    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 exécutée 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).

    Vous devez donc append 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 exécutée sur votre bureau), par exemple:

     containerhostname/unix:0 MIT-MAGIC-COOKIE-1  

    Le problème est que le cookie doit être ajouté avec xauth add dans le conteneur:

     touch ~/.Xauthority xauth add containerhostname/unix:0 .  

    Sinon, xauth marque de manière à ce qu’il ne soit vu qu’en dehors du conteneur.

    Le format de cette commande est le suivant:

     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 monter le .Xauthority dans le conteneur. Créez simplement un fichier vierge, comme indiqué, et ajoutez le cookie.

    La réponse de Jürgen Weigert permet de contourner ce FamilyWild 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é hexadécimale pour la session X actuelle de ~/.Xauthority aide de xauth nlist .

    Les étapes essentielles sont donc les suivantes:

    • Extrayez la clé hexadécimale du cookie pour la session X actuelle de l’utilisateur.
    • Créez un nouveau fichier Xauthority dans le conteneur, avec le nom d’hôte du conteneur et la clé hexadécimale partagée (ou créez un cookie avec le type de connexion FamilyWild ).

    J’avoue que je ne comprends pas très bien le fonctionnement de FamilyWild , ni comment les clients xauth ou X filtrent les entrées du fichier Xauthority en fonction de l’endroit où ils sont exécutés. Des informations supplémentaires à ce sujet sont les bienvenues.

    Si vous souhaitez dissortingbuer votre application Docker, vous aurez besoin d’un script de démarrage pour exécuter le conteneur qui obtient la clé hexadécimale pour 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 la mécanique du processus d’autorisation:

    • An X client (ie GUI application) running in the container looks in the Xauthority file for a cookie entry that matches the container’s hostname and the value of $DISPLAY .
    • If a matching entry is found, the X client passes it with its authorization request to the X server, through the appropriate socket in the /tmp/.X11-unix directory mounted in the container.

    Note: The X11 Unix socket still needs to be mounted in the container, or the container will have no route to the X server. Most dissortingbutions disable TCP access to the X server by default for security reasons.

    For additional information, and to better grasp how the X client/server relationship works, it’s also helpful to look at the example case of SSH X forwarding:

    • The SSH server running on a remote machine emulates its own X server.
    • It sets the value of $DISPLAY in the SSH session to point to its own X server.
    • It uses xauth to create a new cookie for the remote host, and adds it to the Xauthority files for both the local and remote users.
    • When GUI apps are started, they talk to SSH’s emulated X server.
    • The SSH server forwards this data back to the SSH client on your local desktop.
    • The local SSH client sends the data to the X server session running on your desktop, as if the SSH client was actually an X client (ie GUI app).
    • The X server uses the received data to render the GUI on your desktop.
    • At the start of this exchange, the remote X client also sends an authorization request, using the cookie that was just created. The local X server compares it with its local copy.

    The other solutions should work, but here is a solution for docker-compose .

    To fix that error, you need to pass $DISPLAY and .X11-unix to docker, as well as grant the user who started docker access to xhost.

    Within docker-compose.yml: version: '2' services: node: build: . container_name: node environment: - DISPLAY volumes: - /tmp/.X11-unix:/tmp/.X11-unix

    In terminal or script:

    • xhost +si:localuser:$USER
    • xhost +local:docker
    • export DISPLAY=$DISPLAY
    • docker-compose up

    OSX (10.13.6, high sierra)

    Similar to @Nick ‘s answer, but his solution did not work for me.

    First install socat by doing brew install socat , and install XQuartz ( https://www.xquartz.org/ )

    Then followed these steps here ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ ) in the comments section:

     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 

    I was also able to launch CLion from my debian docker container too.