คุณจะรันแอพพลิเคชั่น GUI ในDocker ได้อย่างไรคอนเทนเนอร์อย่างไร?
มีภาพใดที่ตั้งค่าvncserverหรือบางอย่างเพื่อให้คุณสามารถ - เพิ่ม Sandbox Speedbump พิเศษรอบ ๆ พูด Firefox?
คุณจะรันแอพพลิเคชั่น GUI ในDocker ได้อย่างไรคอนเทนเนอร์อย่างไร?
มีภาพใดที่ตั้งค่าvncserverหรือบางอย่างเพื่อให้คุณสามารถ - เพิ่ม Sandbox Speedbump พิเศษรอบ ๆ พูด Firefox?
คำตอบ:
คุณสามารถติดตั้ง vncserver พร้อมกับ Firefox :)
ฉันผลักรูปภาพ vnc / firefox ที่นี่:  docker pull creack/firefox-vnc
รูปภาพถูกสร้างด้วย 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'
สิ่งนี้จะสร้างคอนเทนเนอร์ Docker ที่ใช้ VNC ด้วยรหัสผ่าน 1234 :
สำหรับนักเทียบท่ารุ่น 18 หรือใหม่กว่า:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
สำหรับ Docker เวอร์ชัน 1.3 หรือใหม่กว่า:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
สำหรับนักเทียบท่าก่อนรุ่น 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
              docker inspect <container id>หรือเพียงแค่docker psนั้นคุณเชื่อมต่อกับ IP โฮสต์ของคุณมีพอร์ตที่คุณเพิ่งพบ.
                    Xauthority กลายเป็นปัญหากับระบบที่ใหม่กว่า ฉันสามารถยกเลิกการป้องกันด้วย xhost + ก่อนที่จะเรียกใช้คอนเทนเนอร์นักเทียบท่าของฉันหรือฉันสามารถส่งผ่านไฟล์ Xauthority ที่เตรียมไว้อย่างดี ไฟล์ Xauthority ทั่วไปเป็นชื่อโฮสต์ที่เฉพาะเจาะจง ด้วยนักเทียบท่าแต่ละคอนเทนเนอร์สามารถมีชื่อโฮสต์ที่แตกต่างกัน (ตั้งค่าด้วย docker run -h) แต่แม้การตั้งค่าชื่อโฮสต์ของภาชนะที่เหมือนกันกับระบบโฮสต์ไม่ได้ช่วยในกรณีของฉัน xeyes (ฉันชอบตัวอย่างนี้) เพียงแค่เพิกเฉยคุกกี้เวทย์มนตร์และไม่ส่งข้อมูลรับรองไปยังเซิร์ฟเวอร์ ดังนั้นเราจึงได้รับข้อความแสดงข้อผิดพลาด 'ไม่ได้ระบุโปรโตคอลที่ไม่สามารถเปิดการแสดงผล'
ไฟล์ Xauthority สามารถเขียนในลักษณะที่ชื่อโฮสต์ไม่สำคัญ เราจำเป็นต้องตั้งค่าครอบครัวรับรองความถูกต้องเป็น 'FamilyWild' ฉันไม่แน่ใจว่าถ้า xauth มีบรรทัดคำสั่งที่เหมาะสมสำหรับเรื่องนี้ดังนั้นนี่คือตัวอย่างที่รวม xauth และ sed เข้าด้วยกัน เราต้องเปลี่ยน 16 บิตแรกของเอาต์พุต nlist ค่าของ FamilyWild คือ 65535 หรือ 0xffff
docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes
              -v $XSOCK:$XSOCK -v $XAUTH:$XAUTHก็สามารถย่อให้-v $XSOCK -v $XAUTH
                    :0 $DISPLAYนั่นหมายความว่าและxauth nlist $DISPLAY | ... docker run -ti -e DISPLAY=$DISPLAY ...โดยปกติแล้ว X DISPLAY คือ:0แต่ไม่เสมอไป (และโดยเฉพาะอย่างยิ่งไม่ได้หากคุณกำลังเชื่อมต่อผ่าน ssh -X)
                    /tmp/.docker.xauthไฟล์ที่มี600สิทธิ์ ซึ่งส่งผลให้ xauth ภายใน container docker ไม่สามารถอ่านไฟล์ได้ คุณสามารถตรวจสอบโดยการเรียกใช้xauth listภายในคอนเทนเนอร์นักเทียบท่า ฉันได้เพิ่มchmod 755 $XAUTHหลังจากxauth nlist :0 | ...คำสั่งเพื่อแก้ไขปัญหานี้
                    ฉันเพิ่งพบรายการบล็อกนี้และต้องการแบ่งปันที่นี่กับคุณเพราะฉันคิดว่ามันเป็นวิธีที่ดีที่สุดในการทำและเป็นเรื่องง่ายมาก
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
ข้อดี: 
+ ไม่มีสิ่ง x เซิร์ฟเวอร์ในคอนเทนเนอร์นักเทียบท่า
+ ไม่จำเป็นต้องมีไคลเอ็นต์ / เซิร์ฟเวอร์ vnc 
+ ไม่มี ssh ด้วยการส่งต่อ x
 
+ คอนเทนเนอร์นักเทียบท่าที่เล็กกว่ามาก
ข้อเสีย: 
 
- การใช้ x บนโฮสต์ (ไม่ได้มีไว้สำหรับการแซนด์บ็อกซ์ที่ปลอดภัย)
ในกรณีที่การเชื่อมโยงจะล้มเหลว
ซักวันหนึ่งฉันได้ใส่ส่วนที่สำคัญที่สุดไว้ที่นี่:
 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
สร้างภาพ:
docker build -t firefox .
และคำสั่ง run:
docker run -ti --rm \
   -e DISPLAY=$DISPLAY \
   -v /tmp/.X11-unix:/tmp/.X11-unix \
   firefox
แน่นอนคุณสามารถทำได้ในคำสั่ง run ด้วย sh -c "echo script-here"
คำแนะนำ: สำหรับเสียงลองดูที่: https://stackoverflow.com/a/28985715/2835523
apt-get -y install sudoเพื่อสร้าง/etc/sudoers.dโฟลเดอร์
                    $ xhost +
                    ด้วยปริมาณข้อมูลนักเทียบท่ามันง่ายมากที่จะเปิดเผยซ็อกเก็ต unix โดเมนของ xorg ภายในคอนเทนเนอร์
ตัวอย่างเช่นกับ Dockerfile เช่นนี้:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
คุณสามารถทำสิ่งต่อไปนี้:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
แน่นอนว่านี่เป็นสิ่งเดียวกับ X-forwarding มันให้สิทธิ์การเข้าถึงแบบเต็มไปยังคอนเทนเนอร์ xserver บนโฮสต์ดังนั้นจึงขอแนะนำเฉพาะเมื่อคุณเชื่อถือสิ่งที่อยู่ภายใน
หมายเหตุ:หากคุณกังวลเกี่ยวกับความปลอดภัยทางออกที่ดีกว่าคือการ จำกัด แอพด้วยการควบคุมการเข้าถึงแบบบังคับหรือแบบอิงบทบาท นักเทียบท่าบรรลุความโดดเดี่ยวที่ดี แต่มันถูกออกแบบมาโดยมีจุดประสงค์ที่แตกต่างกัน ใช้AppArmor , SELinuxหรือGrSecurityซึ่งออกแบบมาเพื่อแก้ไขข้อกังวลของคุณ
xhost +บนโฮสต์
                    xhost +localจำเป็น มันจะเป็นการดีกว่าที่จะทำให้~/.Xauthorityไฟล์มีอยู่ในคอนเทนเนอร์อย่างไรก็ตามเพื่อให้สามารถตรวจสอบตัวเองได้
                    Can't open display: :0มีข้อผิดพลาด ความคิดใด ๆ
                    xhost +si:localuser:$USERอนุญาตเพียงผู้ใช้เริ่มภาชนะ
                    คุณยังสามารถใช้ subuser: https://github.com/timthelion/subuser
สิ่งนี้ช่วยให้คุณสามารถบรรจุแอพ gui มากมายใน docker Firefox และ emacs ได้รับการทดสอบแล้ว ด้วย firefox, webGL ไม่ทำงาน Chromium ไม่ทำงานเลย
แก้ไข: เสียงใช้งานได้!
แก้ไข 2: ในเวลาตั้งแต่ฉันโพสต์นี้ subuser มีความก้าวหน้าอย่างมาก ตอนนี้ผมมีเว็บไซต์ขึ้นsubuser.orgและรูปแบบการรักษาความปลอดภัยใหม่สำหรับการเชื่อมต่อ X11 ผ่าน XPRA แก้
Jürgen Weigertมีคำตอบที่ดีที่สุดสำหรับฉันบน Ubuntu แต่บน OSX นักเทียบท่าทำงานภายใน VirtualBox ดังนั้นโซลูชันจึงไม่ทำงานหากไม่มีงานเพิ่มเติม
ฉันได้มันทำงานกับส่วนผสมเพิ่มเติมเหล่านี้:
ฉันขอขอบคุณความคิดเห็นของผู้ใช้ในการปรับปรุงคำตอบนี้สำหรับ OSX ฉันไม่แน่ใจว่าซ็อกเก็ตการส่งต่อสำหรับ X ปลอดภัย แต่การใช้งานที่ฉันตั้งใจไว้สำหรับการเรียกใช้คอนเทนเนอร์นักเทียบท่าเฉพาะที่เท่านั้น
นอกจากนี้สคริปต์นั้นค่อนข้างบอบบางที่ไม่ได้รับที่อยู่ IP ของเครื่องเนื่องจากอยู่บนเครือข่ายไร้สายในพื้นที่ของเราดังนั้นจึงเป็น IP แบบสุ่มเสมอ
สคริปต์ BASH ที่ฉันใช้เพื่อเปิดคอนเทนเนอร์:
#!/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
ฉันสามารถทำให้ xeyes และ matplotlib ทำงานด้วยวิธีนี้ได้
ง่ายขึ้นเล็กน้อยใน Windows 7+ ด้วย MobaXterm:
run_docker.bash:
#!/usr/bin/env bash
CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)
docker run \
    -it \
    --rm \
    --user=$USER \
    --workdir="/home/$USER" \
    -v "/c/Users/$USER:/home/$USER:rw" \
    -e DISPLAY \
    $CONTAINER \
    $COMMAND
              error: XDG_RUNTIME_DIR not set in the environment. Error: cannot open display: VAIO:0.0คุณเจออะไรแบบนี้เหรอ?
                    การแชร์โฮสต์แสดง: 0 ตามที่ระบุในคำตอบอื่น ๆ มีสองข้อเสีย:
xevหรือเป็นไปได้และการควบคุมระยะไกลของการใช้งานเป็นเจ้าภาพด้วยxinputxdotool--ipc=host)ด้านล่างสคริปต์ตัวอย่างเพื่อเรียกใช้อิมเมจนักเทียบท่าใน Xephyr ที่จัดการปัญหานี้
--cap-drop ALL --security-opt no-new-privilegesการรักษาความปลอดภัยตู้คอนเทนเนอร์จะดีขึ้นด้วย ผู้ใช้คอนเทนเนอร์ยังไม่ได้รูทสคริปต์คาดว่าจะมีข้อโต้แย้งบางอย่างเป็นครั้งแรกผู้จัดการหน้าต่างโฮสต์ที่จะทำงานใน Xephyr ที่สองภาพนักเทียบท่าที่สามทางเลือกคำสั่งภาพที่จะดำเนินการ หากต้องการเรียกใช้สภาพแวดล้อมเดสก์ท็อปในตัวเทียบท่าใช้ ":" แทนที่จะเป็นตัวจัดการหน้าต่างโฮสต์
การปิดหน้าต่าง Xephyr ยุติการใช้งานคอนเทนเนอร์ของนักเทียบท่า การยกเลิกแอปพลิเคชันที่ถูกเชื่อมต่อจะปิดหน้าต่าง Xephyr
ตัวอย่าง:
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfmxephyrdocker  :  x11docker/lxdexephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.romสคริปต์ 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
สคริปต์นี้จะคงที่x11docker วิกิพีเดีย สคริปต์ขั้นสูงเพิ่มเติมนั้นคือx11dockerที่รองรับคุณสมบัติต่างๆเช่นการเร่งความเร็วของ GPU เว็บแคมและการแบ่งปันเครื่องพิมพ์เป็นต้น
ต่อไปนี้เป็นโซลูชันที่มีน้ำหนักเบาที่หลีกเลี่ยงการติดตั้งXเซิร์ฟเวอร์vncเซิร์ฟเวอร์หรือsshddaemon บนคอนเทนเนอร์ สิ่งที่ได้รับจากความเรียบง่ายมันเสียความปลอดภัยและความเหงา
ก็ถือว่าคุณเชื่อมต่อกับเครื่องโฮสต์ที่ใช้sshกับX11การส่งต่อ
ในการsshdกำหนดค่าของโฮสต์เพิ่มบรรทัด
X11UseLocalhost no
เพื่อให้พอร์ตเซิร์ฟเวอร์เอ็กซ์ส่งต่อในพื้นที่ที่มีการเปิดในการเชื่อมต่อทั้งหมด (ไม่เพียงlo) docker0และโดยเฉพาะอย่างยิ่งในอินเตอร์เฟซเสมือนหาง
คอนเทนเนอร์เมื่อเรียกใช้จำเป็นต้องเข้าถึง.Xauthorityไฟล์เพื่อให้สามารถเชื่อมต่อกับเซิร์ฟเวอร์ เพื่อที่จะทำเช่นนั้นเราได้กำหนดปริมาณการอ่านอย่างเดียวซึ่งชี้ไปยังโฮมไดเร็กตอรี่ของโฮสต์ (อาจไม่ใช่ความคิดที่ฉลาด!) และตั้งค่าXAUTHORITYตัวแปรตามนั้น
docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
นั่นไม่เพียงพอเราต้องผ่านตัวแปร DISPLAY จากโฮสต์ แต่แทนที่ชื่อโฮสต์ด้วย ip:
-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")
เราสามารถกำหนดนามแฝง:
 alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'
และทดสอบแบบนี้:
dockerX11run centos xeyes
              .Xauthority -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
                    X11UseLocalhostคุณสามารถใช้ตัวเลือกเพิ่มเติม--net=hostสำหรับdocker runคำสั่ง (ดูที่นี่ )
                    --net=hostเป็นความคิดที่ไม่ดีเหมือนตอนนี้ถ้าคุณเปิดพอร์ตในคอนเทนเนอร์มันจะเปิดในโฮสต์ด้วย ...
                    ในขณะที่คำตอบของJürgen Weigertครอบคลุมการแก้ปัญหาเป็นหลัก แต่ก็ไม่ชัดเจนสำหรับฉันในตอนแรกที่อธิบายไว้ที่นั่น ดังนั้นฉันจะเพิ่มการใช้เวลาของฉันในกรณีที่คนอื่นต้องการชี้แจง
ปิดแรกเอกสารที่เกี่ยวข้องเป็นmanpage การรักษาความปลอดภัย X
แหล่งข้อมูลออนไลน์มากมายแนะนำให้ติดตั้งซ็อกเก็ตยูนิกซ์ X11 และ~/.Xauthorityไฟล์ลงในภาชนะ โซลูชันเหล่านี้มักจะทำงานได้ด้วยโชคโดยไม่เข้าใจว่าทำไมเช่นผู้ใช้คอนเทนเนอร์จบลงด้วย UID เดียวกันกับผู้ใช้ดังนั้นจึงไม่จำเป็นต้องมีการอนุญาตคีย์เวทย์
ก่อนอื่นไฟล์ Xauthority มีโหมด 0600 ดังนั้นผู้ใช้คอนเทนเนอร์จะไม่สามารถอ่านได้เว้นแต่จะมี UID เดียวกัน
แม้ว่าคุณจะคัดลอกไฟล์ลงในคอนเทนเนอร์และเปลี่ยนความเป็นเจ้าของ แต่ก็ยังมีปัญหาอื่นอยู่ หากคุณทำงานxauth listบนโฮสต์และคอนเทนเนอร์ด้วยXauthorityไฟล์เดียวกันคุณจะเห็นรายการที่แตกต่างกัน นี่เป็นเพราะxauthตัวกรองรายการขึ้นอยู่กับที่มันทำงาน
ไคลเอ็นต์ X ในภาชนะ (เช่นแอป GUI) xauthจะทำงานเช่นเดียวกับ กล่าวอีกนัยหนึ่งจะไม่เห็นคุกกี้มายากลสำหรับเซสชัน X ที่ทำงานบนเดสก์ท็อปของผู้ใช้ แต่จะเห็นรายการสำหรับเซสชัน X "ระยะไกล" ทั้งหมดที่คุณเปิดก่อนหน้านี้ (อธิบายไว้ด้านล่าง)
ดังนั้นสิ่งที่คุณต้องทำคือเพิ่มรายการใหม่ด้วยชื่อโฮสต์ของภาชนะบรรจุและคีย์เลขฐานสิบหกเดียวกันกับคุกกี้โฮสต์ (เช่นเซสชัน X ที่ทำงานบนเดสก์ท็อปของคุณ) เช่น:
containerhostname/unix:0   MIT-MAGIC-COOKIE-1   <shared hex key>
สิ่งที่จับได้คือต้องเพิ่มคุกกี้xauth addภายในคอนเทนเนอร์:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
มิฉะนั้นติดxauthแท็กในลักษณะที่จะเห็นเฉพาะนอกภาชนะ
รูปแบบสำหรับคำสั่งนี้คือ:
xauth add hostname/$DISPLAY protocol hexkey
ซึ่ง.เป็นตัวแทนของMIT-MAGIC-COOKIE-1โปรโตคอล
หมายเหตุ:ไม่จำเป็นต้องคัดลอกหรือผูกติด.Xauthorityกับภาชนะ เพียงสร้างไฟล์เปล่าดังที่แสดงแล้วเพิ่มคุกกี้
คำตอบของJürgen Weigert แก้ไขโดยใช้FamilyWildประเภทการเชื่อมต่อเพื่อสร้างไฟล์สิทธิอำนาจใหม่บนโฮสต์และคัดลอกลงในคอนเทนเนอร์ โปรดทราบว่ามันเป็นครั้งแรกที่สำคัญสารสกัดจากฐานสิบหกสำหรับเซสชัน X ปัจจุบันจากการใช้~/.Xauthorityxauth nlist
ดังนั้นขั้นตอนสำคัญคือ:
FamilyWildประเภทการเชื่อมต่อ)ฉันยอมรับว่าฉันไม่เข้าใจวิธีการFamilyWildทำงานหรือวิธีที่ดีที่สุดxauthหรือลูกค้า X กรองรายการจากไฟล์ Xauthority ขึ้นอยู่กับที่พวกเขาทำงาน ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ยินดีต้อนรับ  
หากคุณต้องการกระจายแอพ Docker ของคุณคุณจะต้องมีสคริปต์เริ่มต้นสำหรับการเรียกใช้คอนเทนเนอร์ที่ได้รับคีย์เลขฐานสิบสำหรับเซสชัน X ของผู้ใช้และนำเข้าลงในคอนเทนเนอร์ด้วยวิธีใดวิธีหนึ่งจากสองวิธีที่อธิบายไว้ก่อนหน้านี้
นอกจากนี้ยังช่วยให้เข้าใจกลไกของกระบวนการอนุญาต:
$DISPLAYที่ทำงานในภาชนะที่มีลักษณะในแฟ้มดิสเพลย์สำหรับรายการคุกกี้ที่ตรงกับชื่อโฮสต์คอนเทนเนอร์และความคุ้มค่าของ/tmp/.X11-unixไดเร็กทอรีที่เมาท์ในคอนเทนเนอร์หมายเหตุ:ซ็อกเก็ต X11 Unix ยังคงต้องติดตั้งในคอนเทนเนอร์มิฉะนั้นคอนเทนเนอร์จะไม่มีเส้นทางไปยังเซิร์ฟเวอร์ X การกระจายส่วนใหญ่ปิดใช้งานการเข้าถึง TCP ไปยังเซิร์ฟเวอร์ X โดยค่าเริ่มต้นด้วยเหตุผลด้านความปลอดภัย
สำหรับข้อมูลเพิ่มเติมและเพื่อให้เข้าใจการทำงานของความสัมพันธ์ X ไคลเอนต์ / เซิร์ฟเวอร์ได้ดียิ่งขึ้นก็เป็นประโยชน์เช่นกันในการดูกรณีตัวอย่างของการส่งต่อ SSH X:
$DISPLAYในเซสชั่น SSH ให้ชี้ไปที่ X server ของตัวเองxauthเพื่อสร้างคุกกี้ใหม่สำหรับโฮสต์ระยะไกลและเพิ่มลงในXauthorityไฟล์สำหรับผู้ใช้ภายในและระยะไกลนี่ไม่ใช่น้ำหนักเบา แต่เป็นโซลูชันที่ดีที่ให้ความเท่าเทียมกันของคุณสมบัตินักเทียบเคียงกับการจำลองเสมือนบนเดสก์ท็อป ทั้ง Xfce4 หรือ IceWM สำหรับ Ubuntu และ CentOS ทำงานและnoVNCตัวเลือกนี้ทำให้สามารถเข้าถึงได้ง่ายผ่านเบราว์เซอร์
https://github.com/ConSol/docker-headless-vnc-container
มันทำงานได้noVNCดีเท่ากับtigerVNCvncserver จากนั้นจะเรียกstartxใช้ Window Manager ที่กำหนด นอกจากนี้libnss_wrapper.soยังใช้เพื่อจำลองการจัดการรหัสผ่านสำหรับผู้ใช้
xpraเทียบท่าซึ่งเป็น X-root ที่น้อยกว่าxpraนั้นเป็น IMO ที่เหมาะสมที่สุดและมีประสิทธิภาพมากกว่า VNC
                    --device /dev/...จะผ่านไปยังนักเทียบท่าและตั้งค่า--capสิทธิ์ที่จำเป็น นั่นเอาชนะวัตถุประสงค์ของการกักกัน แต่คุณสามารถผ่านอุปกรณ์ต่างๆได้ ด้วยการปรับแต่งมันควรจะเป็นไปได้ผมเชื่อว่ารัน GNOME / KDE ภายใต้ VNC ฉันใช้ X นักเทียบท่าพร้อมการ์ด nvidia (ไม่มี VNC หรือ Xpra) ดังนั้นจึงทำได้
                    โซลูชันที่ให้ไว้ที่http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ดูเหมือนจะเป็นวิธีที่ง่ายในการเริ่มต้นแอปพลิเคชัน GUI จากภายในคอนเทนเนอร์ (ฉันลองใช้ firefox มากกว่า Ubuntu 14.04) แต่ฉันพบว่าต้องมีการเปลี่ยนแปลงเพิ่มเติมเล็กน้อยสำหรับโซลูชันที่โพสต์โดยผู้เขียน
โดยเฉพาะสำหรับการเรียกใช้คอนเทนเนอร์ผู้เขียนได้กล่าวถึง:
    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    firefox
แต่ฉันพบว่า (ตามความคิดเห็นเฉพาะในเว็บไซต์เดียวกัน) ที่สองตัวเลือกเพิ่มเติม
    -v $HOME/.Xauthority:$HOME/.Xauthority
และ
    -net=host 
จำเป็นต้องระบุในขณะที่เรียกใช้คอนเทนเนอร์เพื่อให้ Firefox ทำงานอย่างถูกต้อง:
    docker run -ti --rm \
    -e DISPLAY=$DISPLAY \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v $HOME/.Xauthority:$HOME/.Xauthority \
    -net=host \
    firefox
ฉันสร้างภาพนักเทียบท่าพร้อมข้อมูลในหน้านั้นและสิ่งที่ค้นพบเพิ่มเติมเหล่านี้: https://hub.docker.com/r/amanral/ubuntu-firefox/
/tmp/.X11-unixเบ้าตาเลย มันก็ทำงานร่วมกับการติดตั้งและ.Xauthority --net=host
                    /tmp/.X11-unixเป็นปริมาณไม่ทำงานอีกต่อไปเป็นนักเทียบท่าเงียบปฏิเสธปริมาณเมานต์จากไดเรกทอรีเหนียว
                    --network=hostไม่ ช่วยให้คุณเข้าถึงคอนเทนเนอร์สแต็กเครือข่ายของโฮสต์ได้อย่างสมบูรณ์ซึ่งอาจไม่เป็นที่พึงปรารถนาทั้งนี้ขึ้นอยู่กับสิ่งที่คุณพยายามทำ หากคุณเพียงแค่เปิดใช้ GUI ที่มีคอนเทนเนอร์บนเดสก์ท็อปของคุณคุณก็ไม่ควรพลาด
                    มีโซลูชันอื่นโดย lord.garbageเพื่อเรียกใช้แอป GUI ในคอนเทนเนอร์โดยไม่ใช้การส่งต่อ VNC, SSH และ X11 มันถูกกล่าวถึงที่นี่ด้วย
หากคุณต้องการที่จะเรียกใช้โปรแกรมประยุกต์แบบ GUI หัวขาดแล้วอ่านที่นี่ สิ่งที่คุณต้องทำคือการสร้างจอภาพเสมือนด้วยxvfbหรือซอฟต์แวร์อื่นที่คล้ายคลึงกัน สิ่งนี้มีประโยชน์มากหากคุณต้องการเรียกใช้การทดสอบซีลีเนียมกับเบราว์เซอร์
สิ่งที่ไม่ได้กล่าวถึงคือซอฟต์แวร์บางตัวใช้ Sand-Boxing กับตู้คอนเทนเนอร์ Linux ตัวอย่างเช่น Chrome จะไม่ทำงานตามปกติหากคุณไม่ใช้การตั้งค่าสถานะที่เหมาะสม--privilegedเมื่อเรียกใช้คอนเทนเนอร์
ฉันสายไปงานเลี้ยง แต่สำหรับผู้ใช้ Mac ที่ไม่ต้องการที่จะไปลงเส้นทาง XQuartz นี่เป็นตัวอย่างการทำงานที่สร้างภาพ Fedora กับสิ่งแวดล้อมสก์ท็อป (Xfce) โดยใช้และXvfb VNCมันง่ายและใช้งานได้:
บน Mac คุณก็สามารถเข้าถึงได้โดยใช้หน้าจอร่วมกันแอพลิเคชัน (เริ่มต้น), 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
ตรวจสอบreadme ที่เชื่อมโยงเพื่อสร้างและเรียกใช้คำสั่งหากคุณต้องการ / ต้องการ
จากคำตอบของJürgen Weigertฉันมีการปรับปรุงบางอย่าง:
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
ข้อแตกต่างเพียงอย่างเดียวคือมันสร้างไดเรกทอรี $ XAUTH_DIR ซึ่งใช้เพื่อวางไฟล์ $ XAUTH และติดตั้งไดเรกทอรี $ XAUTH_DIR แทนไฟล์ $ XAUTH ลงในคอนเทนเนอร์ตัวเทียบท่า
ประโยชน์ของวิธีนี้คือคุณสามารถเขียนคำสั่งใน /etc/rc.local เพื่อสร้างโฟลเดอร์ว่างชื่อ $ XAUTH_DIR ใน / tmp และเปลี่ยนโหมดเป็น 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
เมื่อระบบรีสตาร์ทก่อนเข้าสู่ระบบของผู้ใช้นักเทียบท่าจะทำการติดตั้งไดเรกทอรี $ XAUTH_DIR โดยอัตโนมัติหากนโยบายการรีสตาร์ทคอนเทนเนอร์เป็น "เสมอ" หลังจากล็อกอินของผู้ใช้คุณสามารถเขียนคำสั่งใน ~ / .profile ซึ่งสร้างไฟล์ $ XAUTH จากนั้นคอนเทนเนอร์จะใช้ไฟล์ $ 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
หลังจากนั้นคอนเทนเนอร์จะรับไฟล์ Xauthority โดยอัตโนมัติทุกครั้งที่ระบบรีสตาร์ทและลงชื่อเข้าใช้ของผู้ใช้
โซลูชั่นอื่น ๆ ควรจะทำงาน docker-composeแต่นี่คือการแก้ปัญหาสำหรับ
ในการแก้ไขข้อผิดพลาดนั้นคุณจะต้องส่ง $ DISPLAY และ. X11-unix ไปยังนักเทียบท่ารวมถึงให้สิทธิ์ผู้ใช้ที่เริ่มนักเข้าถึงท่าเพื่อเข้าถึง xhost
ภายในdocker-compose.ymlไฟล์:
version: '2'
services:
    node:
        build: .
        container_name: node
        environment:
            - DISPLAY
        volumes:
            - /tmp/.X11-unix:/tmp/.X11-unix
ในเทอร์มินัลหรือสคริปต์:
xhost +si:localuser:$USERxhost +local:dockerexport DISPLAY=$DISPLAYdocker-compose upสำหรับการเรนเดอร์ OpenGL ด้วยไดรเวอร์ Nvidia ให้ใช้ภาพต่อไปนี้:
https://github.com/thewtex/docker-opengl-nvidia
สำหรับการใช้งาน OpenGL อื่น ๆ ตรวจสอบให้แน่ใจว่าภาพมีการนำไปปฏิบัติเช่นเดียวกับโฮสต์
คุณสามารถอนุญาตให้ผู้ใช้ Docker (ที่นี่: รูท) เข้าถึงการแสดงผล 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
              คล้ายกับคำตอบของ@Nickแต่โซลูชันของเขาไม่ได้ผลสำหรับฉัน
ก่อนติดตั้ง socat โดยทำbrew install socatและติดตั้ง XQuartz ( https://www.xquartz.org/ )
จากนั้นทำตามขั้นตอนเหล่านี้ที่นี่ ( http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/ ) ในส่วนความคิดเห็น:
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
ฉันสามารถเปิด CLion จากคอนเทนเนอร์นักเทียบท่าเดเบียนของฉันได้เช่นกัน
นักเทียบท่าพร้อมเครือข่าย BRIDGE สำหรับ Ubuntu 16.04 พร้อมตัวจัดการจอแสดงผล lightdm:
cd /etc/lightdm/lightdm.conf.d
sudo nano user.conf
[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp
คุณสามารถใช้การอนุญาตส่วนตัวเพิ่มเติม
xhost +
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name
              อีกคำตอบหนึ่งในกรณีที่คุณสร้างภาพ:
เรียกใช้ตัวเทียบท่าที่ไม่มี sudo ( วิธีแก้ไขตัวเทียบท่า: มีปัญหาถูกปฏิเสธสิทธิ์ )
แชร์ USER & home & passwd เดียวกันระหว่างโฮสต์และคอนเทนเนอร์แชร์ (เคล็ดลับ: ใช้รหัสผู้ใช้แทนชื่อผู้ใช้)
โฟลเดอร์ dev สำหรับ libs ที่ขึ้นอยู่กับไดรเวอร์ให้ทำงานได้ดี
บวก X11 ไปข้างหน้า
    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
คุณอาจถามว่าอะไรคือจุดที่จะใช้นักเทียบท่าหากมีหลายสิ่งเหมือนกัน? เหตุผลหนึ่งที่ฉันคิดได้ก็คือเอาชนะแพ็คเกจการพึ่งพานรก ( https://en.wikipedia.org/wiki/Dependency_hell )
ดังนั้นการใช้งานประเภทนี้จึงเหมาะสำหรับนักพัฒนาที่ฉันคิดว่า
echo ~: / home / $ {USER} --user = id -u ${USER}--env = "DISPLAY" --volume = "/ etc / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
                    ฉันจัดการเพื่อเรียกใช้การสตรีมวิดีโอจากกล้อง USB ที่ใช้opencvในการdockerทำตามขั้นตอนเหล่านี้:
ให้นักเทียบท่าเข้าถึงเซิร์ฟเวอร์ X
xhost +local:docker
สร้างซ็อกเก็ต X11 Unix และไฟล์การพิสูจน์ตัวตน X
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
เพิ่มสิทธิ์ที่เหมาะสม
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
ตั้งค่าความเร็วในการเรนเดอร์ Qt เป็น "เนทีฟ" ดังนั้นจึงไม่ข้าม X11 เอ็นจิ้นการเรนเดอร์
export QT_GRAPHICSSYSTEM=native
บอก Qt ว่าอย่าใช้ MIT-SHM (หน่วยความจำที่ใช้ร่วมกัน) - วิธีนี้ควรปลอดภัยกว่าด้วยเช่นกัน
export QT_X11_NO_MITSHM=1
อัพเดตคำสั่ง run docker
docker run -it \
           -e DISPLAY=$DISPLAY \
           -e XAUTHORITY=$XAUTH \
           -v $XSOCK:$XSOCK \
           -v $XAUTH:$XAUTH \
           --runtime=nvidia \
           --device=/dev/video0:/dev/video0 \
           nvcr.io/nvidia/pytorch:19.10-py3
หมายเหตุ: เมื่อคุณเสร็จสิ้นโครงการให้คืนการควบคุมการเข้าถึงตามค่าเริ่มต้น - xhost -local:docker
รายละเอียดเพิ่มเติม: การใช้ GUI กับ Docker
เครดิต: การตรวจจับวัตถุตามเวลาจริงและการประมวลผลวิดีโอโดยใช้ Tensorflow, OpenCV และ Docker