Can you run GUI applications in a Docker container?

前端 未结 22 2473
南旧
南旧 2020-11-22 06:12

How can you run GUI applications in a Docker container?

Are there any images that set up vncserver or something so that you can - for example - add an e

相关标签:
22条回答
  • 2020-11-22 06:49

    You can simply install a vncserver along with Firefox :)

    I pushed an image, vnc/firefox, here: docker pull creack/firefox-vnc

    The image has been made with this 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'
    

    This will create a Docker container running VNC with the password 1234:

    For Docker version 18 or newer:

    docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
    

    For Docker version 1.3 or newer:

    docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
    

    For Docker before version 1.3:

    docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
    
    0 讨论(0)
  • 2020-11-22 06:49

    Sharing host display :0, as stated in some other answers, has two drawbacks:

    • It breaks container isolation due to some X security leaks. For example, keylogging with xev or xinput is possible, and remote control of host applications with xdotool.
    • Applications can have rendering glitches and bad RAM access errors due to missing shared memory for X extension MIT-SHM. (Can also be fixed with isolation degrading option --ipc=host).

    Below an example script to run a docker image in Xephyr that addresses this issues.

    • It avoids X security leaks as the docker applications run in a nested X server.
    • MIT-SHM is disabled to avoid RAM access failures.
    • Container security is improved with --cap-drop ALL --security-opt no-new-privileges. Also the container user is not root.
    • An X cookie is created to restrict access to Xephyr display.

    The script expects some arguments, first a host window manager to run in Xephyr, second a docker image, optionally third an image command to be executed. To run a desktop environment in docker, use ":" instead of a host window manager.

    Closing Xephyr window terminates docker container applications. Terminating the dockered applications closes Xephyr window.

    Examples:

    • 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="$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
    

    This script is maintained at x11docker wiki. A more advanced script is x11docker that also supports features like GPU acceleration, webcam and printer sharing and so on.

    0 讨论(0)
  • 2020-11-22 06:49

    The solution given at http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ does seem to be an easy way of starting GUI applications from inside the containers ( I tried for firefox over ubuntu 14.04) but I found that a small additional change is required to the solution posted by the author.

    Specifically, for running the container, the author has mentioned:

        docker run -ti --rm \
        -e DISPLAY=$DISPLAY \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        firefox
    

    But I found that (based on a particular comment on the same site) that two additional options

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

    and

        -net=host 
    

    need to be specified while running the container for firefox to work properly:

        docker run -ti --rm \
        -e DISPLAY=$DISPLAY \
        -v /tmp/.X11-unix:/tmp/.X11-unix \
        -v $HOME/.Xauthority:$HOME/.Xauthority \
        -net=host \
        firefox
    

    I have created a docker image with the information on that page and these additional findings: https://hub.docker.com/r/amanral/ubuntu-firefox/

    0 讨论(0)
  • 2020-11-22 06:49

    This is not lightweight but is a nice solution that gives docker feature parity with full desktop virtualization. Both Xfce4 or IceWM for Ubuntu and CentOS work, and the noVNC option makes for an easy access through a browser.

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

    It runs noVNC as well as tigerVNC's vncserver. Then it calls startx for given Window Manager. In addition, libnss_wrapper.so is used to emulate password management for the users.

    0 讨论(0)
提交回复
热议问题