คุณจะรันแอพพลิเคชั่น 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
หรือเป็นไปได้และการควบคุมระยะไกลของการใช้งานเป็นเจ้าภาพด้วยxinput
xdotool
--ipc=host
)ด้านล่างสคริปต์ตัวอย่างเพื่อเรียกใช้อิมเมจนักเทียบท่าใน Xephyr ที่จัดการปัญหานี้
--cap-drop ALL --security-opt no-new-privileges
การรักษาความปลอดภัยตู้คอนเทนเนอร์จะดีขึ้นด้วย ผู้ใช้คอนเทนเนอร์ยังไม่ได้รูทสคริปต์คาดว่าจะมีข้อโต้แย้งบางอย่างเป็นครั้งแรกผู้จัดการหน้าต่างโฮสต์ที่จะทำงานใน Xephyr ที่สองภาพนักเทียบท่าที่สามทางเลือกคำสั่งภาพที่จะดำเนินการ หากต้องการเรียกใช้สภาพแวดล้อมเดสก์ท็อปในตัวเทียบท่าใช้ ":" แทนที่จะเป็นตัวจัดการหน้าต่างโฮสต์
การปิดหน้าต่าง Xephyr ยุติการใช้งานคอนเทนเนอร์ของนักเทียบท่า การยกเลิกแอปพลิเคชันที่ถูกเชื่อมต่อจะปิดหน้าต่าง Xephyr
ตัวอย่าง:
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
xephyrdocker : x11docker/lxde
xephyrdocker 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
เซิร์ฟเวอร์หรือsshd
daemon บนคอนเทนเนอร์ สิ่งที่ได้รับจากความเรียบง่ายมันเสียความปลอดภัยและความเหงา
ก็ถือว่าคุณเชื่อมต่อกับเครื่องโฮสต์ที่ใช้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 ปัจจุบันจากการใช้~/.Xauthority
xauth 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
ดีเท่ากับtigerVNC
vncserver จากนั้นจะเรียก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:$USER
xhost +local:docker
export DISPLAY=$DISPLAY
docker-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