web-dev-qa-db-fra.com

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

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?

367
Will

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
229
creack

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
185
Jürgen Weigert

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

62
A. Binzxxxxxx

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.

49
Aryeh Leib Taurog

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 .

26
timthelion

OSX

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:

  1. Xquartz (OSX n'est plus livré avec le serveur X11)
  2. transfert de socle avec socat (brasser installer socat)
  3. script bash pour lancer le conteneur

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.

Windows 7+

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

  1. Installer MobaXterm pour Windows
  2. Démarrer MobaXterm
  3. Configurer le serveur X: Paramètres -> X11 (onglet) -> définir X11 Accès à distance à complet
  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

24
Nick

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
18
danidiaz

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

  • Il rompt l'isolement du conteneur en raison de certaines fuites de sécurité X. Par exemple, l'enregistrement au clavier avec xev ou xinput est possible, et le contrôle à distance d'applications hôtes avec xdotool.
  • Les applications peuvent présenter des problèmes de rendu et des erreurs d'accès incorrect RAM en raison d'une mémoire partagée manquante pour l'extension X MIT-SHM. (Peut également être corrigé avec l'option de dégradation de l'isolement --ipc=Host).

Ci-dessous, un exemple de script pour exécuter une image de menu fixe dans Xephyr qui résout ce problème.

  • Cela évite les fuites de sécurité X lorsque les applications de menu fixe s'exécutent sur un serveur X imbriqué.
  • MIT-SHM est désactivé pour éviter RAM échecs d'accès.
  • La sécurité des conteneurs est améliorée avec --cap-drop ALL --security-opt no-new-privileges. De plus, l'utilisateur du conteneur est et non root.
  • Un cookie X est créé pour limiter l'accès à l'affichage Xephyr.

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.

16
mviereck

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.

12
dashesy

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

. 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:

  • Extrayez la clé hexagonale du cookie pour la session X en cours de l'utilisateur.
  • Créez un nouveau fichier Xauthority dans le conteneur, avec le nom d'hôte du conteneur et la clé hexagonale partagée (ou créez un cookie avec le type de connexion 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:

  • Un client X (c'est-à-dire une application graphique) exécuté dans le conteneur recherche dans le fichier Xauthority une entrée de cookie correspondant 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 socket approprié du répertoire /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:

  • Le serveur SSH s'exécutant sur une machine distante émule son propre serveur X.
  • Il définit la valeur de $DISPLAY dans la session SSH pour qu'elle pointe 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 des utilisateurs locaux et distants.
  • Lorsque les applications de l'interface graphique sont démarrées, elles 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 de serveur X exécutée sur votre bureau, comme si le client SSH était en réalité un client X (c'est-à-dire une application d'interface graphique).
  • Le serveur X utilise les données reçues pour rendre l'interface graphique sur votre bureau.
  • Au début de cet échange, le client X distant envoie également une demande d'autorisation à l'aide du cookie qui vient d'être créé. Le serveur X local le compare à sa copie locale.
12
orodbhen

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/

10
Anshuman Manral

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.

7
niutech

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.

7
Pithikos

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.

5
allenyllee

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.

5
Vince

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.

3
Matt McCormick

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
3
wedesoft

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
3
nathangeorge1

Encore une autre réponse au cas où vous avez déjà construit l'image:

  1. invoquer le docker sans Sudo ( Comment résoudre le docker: problème d'autorisation refusée )

  2. 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)

  3. le dossier dev pour que les bibliothèques dépendantes du pilote fonctionnent bien

  4. 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.

1
TingQian LI

OSX (10.13.6, High Sierra)

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.

1
nommer

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
1
dabizharoman