คุณสามารถรันแอปพลิเคชั่น GUI ในคอนเทนเนอร์ Docker ได้หรือไม่?


409

คุณจะรันแอพพลิเคชั่น GUI ในDocker ได้อย่างไรคอนเทนเนอร์อย่างไร?

มีภาพใดที่ตั้งค่าvncserverหรือบางอย่างเพื่อให้คุณสามารถ - เพิ่ม Sandbox Speedbump พิเศษรอบ ๆ พูด Firefox?


คำถามนี้ดูเหมือนจะเกี่ยวข้องกับ Linux เท่านั้น (ขึ้นอยู่กับอายุและเนื้อหาของคำตอบ) ไม่ใช่ Windows ถ้าเป็นเช่นนั้นเราสามารถแก้ไขชื่อเพื่อชี้แจงเรื่องนี้ได้หรือไม่? ขอบคุณ
UuDdLrLrSs


ตรวจสอบคู่มือผู้ใช้ภาชนะบรรจุการสร้างภาพ HPCสำหรับแนวคิดบางอย่าง
kenorb

คำตอบ:


238

คุณสามารถติดตั้ง 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

2
ฉันจะใช้ไคลเอนต์ VNC เพื่อดูระยะไกลนี้ได้อย่างไร การพิมพ์ในพอร์ต IP + นั้นใช้งานไม่ได้
user94154

17
ครั้งแรกที่คุณจะต้องตรวจสอบพอร์ตการจัดสรร (โดยการทำdocker inspect <container id>หรือเพียงแค่docker psนั้นคุณเชื่อมต่อกับ IP โฮสต์ของคุณมีพอร์ตที่คุณเพิ่งพบ.
creack

9
อิมเมจ creackfirefox-vnc ล้มเหลวโดยมีข้อผิดพลาด: ป้อนรหัสผ่าน VNC: stty: อินพุตมาตรฐาน: ioctl ที่ไม่เหมาะสมสำหรับอุปกรณ์วิดเจ็ต: ไม่มีไฟล์หรือไดเรกทอรี stty: อินพุตมาตรฐาน: ioctl ที่ไม่เหมาะสมสำหรับอุปกรณ์ x11vnc -usepw: ไม่พบรหัสผ่าน
alfonsodev

6
ใช้นักเทียบท่าอย่างดี> เรียกใช้แอป GUI กับ Docker fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker
Dennis C

7
ไม่มีชื่อผู้ใช้รหัสผ่านที่ระบุไว้อย่างชัดเจนในคำตอบและลูกค้า vnc ใด ๆ ที่จะทำ ในกรณีของฉันฉันชอบ osx ดั้งเดิม (จากตัวค้นหากดคำสั่ง + K และเชื่อมต่อกับ vnc: // <docker ip>: <พอร์ตที่เปิดเผยคอนเทนเนอร์>)
creack

195

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

8
เพียงบันทึกย่อ-v $XSOCK:$XSOCK -v $XAUTH:$XAUTHก็สามารถย่อให้-v $XSOCK -v $XAUTH
เล็ก

2
@PiotrAleksanderChmielowski ที่ไม่ได้ทำงานสำหรับฉันรุ่น Docker 1.12.0, สร้าง 8eab29e
tbc0

14
@Dirk: คุณอาจต้องการที่จะเปลี่ยนด้วย:0 $DISPLAYนั่นหมายความว่าและxauth nlist $DISPLAY | ... docker run -ti -e DISPLAY=$DISPLAY ...โดยปกติแล้ว X DISPLAY คือ:0แต่ไม่เสมอไป (และโดยเฉพาะอย่างยิ่งไม่ได้หากคุณกำลังเชื่อมต่อผ่าน ssh -X)
johndodo

4
ใน Ubuntu 16.04 xauth สร้าง/tmp/.docker.xauthไฟล์ที่มี600สิทธิ์ ซึ่งส่งผลให้ xauth ภายใน container docker ไม่สามารถอ่านไฟล์ได้ คุณสามารถตรวจสอบโดยการเรียกใช้xauth listภายในคอนเทนเนอร์นักเทียบท่า ฉันได้เพิ่มchmod 755 $XAUTHหลังจากxauth nlist :0 | ...คำสั่งเพื่อแก้ไขปัญหานี้
Abai

2
@Abai ทำไมใช้ 755 ถ้า 444 หรือ 644 เพียงพอหรือไม่
Daniel Alder

68

ฉันเพิ่งพบรายการบล็อกนี้และต้องการแบ่งปันที่นี่กับคุณเพราะฉันคิดว่ามันเป็นวิธีที่ดีที่สุดในการทำและเป็นเรื่องง่ายมาก

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


ฉันจะทำสิ่งนี้บน windows 7 ได้อย่างไร ฉันจำเป็นต้องติดตั้งเซิร์ฟเวอร์ X หรือไม่
walkignison

3
เนื่องจากคำตอบส่วนใหญ่ที่นี่ใช้กับยูนิกซ์เท่านั้นฉันคิดว่า - จนกว่า windows จะรองรับระบบ X server window
A. Binzxxxxxx

คุณคิดว่ามันสามารถใช้งานได้หรือไม่ถ้าฉันติดตั้งเซิร์ฟเวอร์ X บน windows หรือรวมเซิร์ฟเวอร์ X ไว้ในคอนเทนเนอร์ Docker ของฉันด้วย
walkignison

1
ฉันคิดว่าคุณต้องติดตั้งใน Dockerfile apt-get -y install sudoเพื่อสร้าง/etc/sudoers.dโฟลเดอร์
mulg0r

1
อาจจำเป็นต้องอนุญาตการเชื่อมต่อไปยัง X จากโฮสต์ใด ๆ ด้วย$ xhost +
Bandoos

52

ด้วยปริมาณข้อมูลนักเทียบท่ามันง่ายมากที่จะเปิดเผยซ็อกเก็ต 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ซึ่งออกแบบมาเพื่อแก้ไขข้อกังวลของคุณ


5
คุณต้องอนุญาตการเข้าถึง X Server จากโฮสต์อื่นโดยใช้เครื่องมือเช่น xhost เพื่อเปิดขึ้นอย่างสมบูรณ์ใช้งานxhost +บนโฮสต์
ทัลลี

3
@Tully เท่านั้นที่xhost +localจำเป็น มันจะเป็นการดีกว่าที่จะทำให้~/.Xauthorityไฟล์มีอยู่ในคอนเทนเนอร์อย่างไรก็ตามเพื่อให้สามารถตรวจสอบตัวเองได้
Aryeh Leib Taurog

3
คุณจัดการเพื่อให้มันทำงานบน Mac (ใช้ boot2docker)?
Karl Forner

4
มันใช้งานได้ดีสำหรับฉันบนแล็ปท็อป Ubuntu 14.04 ที่มีตัวเชื่อมต่อ 1.5 รุ่นก่อนหน้านี้ แต่ตอนนี้ล้มเหลวสำหรับฉันในอูบุนตู 15.04, นักเทียบท่า 1.6.2 Can't open display: :0มีข้อผิดพลาด ความคิดใด ๆ
cboettig

6
ฉันเคยxhost +si:localuser:$USERอนุญาตเพียงผู้ใช้เริ่มภาชนะ
Nick Breen

26

คุณยังสามารถใช้ subuser: https://github.com/timthelion/subuser

สิ่งนี้ช่วยให้คุณสามารถบรรจุแอพ gui มากมายใน docker Firefox และ emacs ได้รับการทดสอบแล้ว ด้วย firefox, webGL ไม่ทำงาน Chromium ไม่ทำงานเลย

แก้ไข: เสียงใช้งานได้!

แก้ไข 2: ในเวลาตั้งแต่ฉันโพสต์นี้ subuser มีความก้าวหน้าอย่างมาก ตอนนี้ผมมีเว็บไซต์ขึ้นsubuser.orgและรูปแบบการรักษาความปลอดภัยใหม่สำหรับการเชื่อมต่อ X11 ผ่าน XPRA แก้


3
โปรดทราบว่า subuser นั้นยังใหม่และยังไม่ได้ทดสอบ หากคุณพบปัญหาใด ๆ โปรดส่งรายงานข้อผิดพลาด!
timthelion

ฉันจะหลีกเลี่ยง X11 หากมีวิธีที่คุณสามารถทำได้ แอพนักฆ่าของคุณกำลังเรียกใช้พร็อกซี tor ในตัวเชื่อมต่อและเรียกใช้เบราว์เซอร์เต็มรูปแบบที่มีปลั๊กอินในตัวเชื่อมต่อเด็กซึ่งไฟร์วอลล์ ฯลฯ จะบังคับให้เครือข่ายทั้งหมดออกผ่านตัวเชื่อมต่อ tor สิ่งนี้จะเรียกใช้รอบ ๆ ชุดเบราว์เซอร์ของ tor ปัจจุบันเพื่อการใช้งานเว็บได้เพราะคุณต้องการให้เนื้อหาสมบูรณ์
จะ

1
ปัญหาของคุณกับการรักษาความปลอดภัย X11 หรือไม่? หรือว่าคุณต้องการทำงานกับ windows? หรือว่าคุณต้องการให้มันทำงานจากระยะไกล ถูกทุกข้อ? ฉันคิดว่าการทำงานกับ vnc นี้เป็นไปได้ค่อนข้าง (แม้ว่าฉันจะไม่ทำให้เป็นวิธีการเริ่มต้นเพราะมันเพิ่มการพึ่งพา vnc) การทำให้ subuser ทำงานจากระยะไกลเป็นไปไม่ได้จริงๆ / เป็นความหมายที่สมบูรณ์ นอกจากนี้ยังมีสิ่งนี้: github.com/rogaha/docker-desktopแต่จากรายงานบั๊กดูเหมือนว่า xpra อาจใช้ไม่ได้ในชีวิตจริง
timthelion

24

OSX

Jürgen Weigertมีคำตอบที่ดีที่สุดสำหรับฉันบน Ubuntu แต่บน OSX นักเทียบท่าทำงานภายใน VirtualBox ดังนั้นโซลูชันจึงไม่ทำงานหากไม่มีงานเพิ่มเติม

ฉันได้มันทำงานกับส่วนผสมเพิ่มเติมเหล่านี้:

  1. Xquartz (OSX ไม่ได้จัดส่งพร้อมกับเซิร์ฟเวอร์ X11 อีกต่อไป)
  2. การส่งต่อซ็อกเก็ตด้วย socat (ชงติดตั้ง socat)
  3. สคริปต์ทุบตีเพื่อเปิดภาชนะ

ฉันขอขอบคุณความคิดเห็นของผู้ใช้ในการปรับปรุงคำตอบนี้สำหรับ 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+

ง่ายขึ้นเล็กน้อยใน Windows 7+ ด้วย MobaXterm:

  1. ติดตั้ง MobaXterm สำหรับ windows
  2. เริ่ม MobaXterm
  3. กำหนดค่าเซิร์ฟเวอร์ X: การตั้งค่า -> X11 (แท็บ) -> ตั้งค่าการเข้าถึงระยะไกล X11ให้เต็ม
  4. ใช้สคริปต์ BASH นี้เพื่อเปิดคอนเทนเนอร์

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 ทำงานบนพีซี


ฉันไม่เข้าใจสิ่งที่คุณหมายถึงโดยสคริปต์ทุบตี - ฉันจะรันใน windows ได้อย่างไร
deller

@deller ฉันทำการพัฒนาซอฟต์แวร์บน windows โดยใช้ GIT ดังนั้นฉันจึงมี GIT-bash shell สำหรับฉัน
Nick

ฉันทำตามขั้นตอน แต่ผมได้รับและerror: XDG_RUNTIME_DIR not set in the environment. Error: cannot open display: VAIO:0.0คุณเจออะไรแบบนี้เหรอ?
user3275095

1
ฉันพบข้อผิดพลาดเกี่ยวกับผู้ใช้ที่ไม่พบเช่น "ไม่มีรายการที่ตรงกันในไฟล์ passwd" โอกาสในการขายใด ๆ
walkignison

19

การแชร์โฮสต์แสดง: 0 ตามที่ระบุในคำตอบอื่น ๆ มีสองข้อเสีย:

  • มันแบ่งการแยกคอนเทนเนอร์เนื่องจากการรั่วไหลของความปลอดภัย X ยกตัวอย่างเช่น keylogging กับxevหรือเป็นไปได้และการควบคุมระยะไกลของการใช้งานเป็นเจ้าภาพด้วยxinputxdotool
  • แอปพลิเคชันสามารถมีการแสดงผลบกพร่องและข้อผิดพลาดการเข้าถึง RAM ที่ไม่ดีเนื่องจากหน่วยความจำที่ใช้ร่วมกันขาดหายไปสำหรับ X extension MIT-SHM (สามารถแก้ไขได้ด้วยตัวเลือกการแยกย่อย--ipc=host)

ด้านล่างสคริปต์ตัวอย่างเพื่อเรียกใช้อิมเมจนักเทียบท่าใน Xephyr ที่จัดการปัญหานี้

  • มันหลีกเลี่ยงการรั่วไหลของความปลอดภัย X เมื่อแอปพลิเคชันตัวเชื่อมต่อทำงานในเซิร์ฟเวอร์ X ที่ซ้อนอยู่
  • MIT-SHM ถูกปิดใช้งานเพื่อหลีกเลี่ยงความล้มเหลวในการเข้าถึง RAM
  • --cap-drop ALL --security-opt no-new-privilegesการรักษาความปลอดภัยตู้คอนเทนเนอร์จะดีขึ้นด้วย ผู้ใช้คอนเทนเนอร์ยังไม่ได้รูท
  • คุกกี้ X ถูกสร้างขึ้นเพื่อ จำกัด การเข้าถึงการแสดงผลของ Xephyr

สคริปต์คาดว่าจะมีข้อโต้แย้งบางอย่างเป็นครั้งแรกผู้จัดการหน้าต่างโฮสต์ที่จะทำงานใน 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 เว็บแคมและการแบ่งปันเครื่องพิมพ์เป็นต้น


18

ต่อไปนี้เป็นโซลูชันที่มีน้ำหนักเบาที่หลีกเลี่ยงการติดตั้ง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

2
(นี่คือที่ดีสำหรับการปพลิเคชันที่เชื่อถือได้สำหรับชนิดของ Sandboxing แม้ว่าคุณต้องการหลีกเลี่ยงการส่งต่อ X-ใด ๆ ..)
Will

1
หากคุณไม่ต้องการติดไดเรกทอรีบ้านทั้งหมดลงในภาชนะที่คุณก็สามารถติดไฟล์ตัวเอง:.Xauthority -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
Robert Haines

2
แทนที่จะเปลี่ยนX11UseLocalhostคุณสามารถใช้ตัวเลือกเพิ่มเติม--net=hostสำหรับdocker runคำสั่ง (ดูที่นี่ )
ingomueller.net

--net=hostเป็นความคิดที่ไม่ดีเหมือนตอนนี้ถ้าคุณเปิดพอร์ตในคอนเทนเนอร์มันจะเปิดในโฮสต์ด้วย ...
MrR

16

ในขณะที่คำตอบของ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

ดังนั้นขั้นตอนสำคัญคือ:

  • แยกคีย์ hex ของคุกกี้สำหรับเซสชัน X ปัจจุบันของผู้ใช้
  • สร้างไฟล์ Xauthority ใหม่ในคอนเทนเนอร์โดยใช้ชื่อโฮสต์คอนเทนเนอร์และคีย์ hex ที่ใช้ร่วมกัน (หรือสร้างคุกกี้ที่มีFamilyWildประเภทการเชื่อมต่อ)

ฉันยอมรับว่าฉันไม่เข้าใจวิธีการFamilyWildทำงานหรือวิธีที่ดีที่สุดxauthหรือลูกค้า X กรองรายการจากไฟล์ Xauthority ขึ้นอยู่กับที่พวกเขาทำงาน ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ยินดีต้อนรับ

หากคุณต้องการกระจายแอพ Docker ของคุณคุณจะต้องมีสคริปต์เริ่มต้นสำหรับการเรียกใช้คอนเทนเนอร์ที่ได้รับคีย์เลขฐานสิบสำหรับเซสชัน X ของผู้ใช้และนำเข้าลงในคอนเทนเนอร์ด้วยวิธีใดวิธีหนึ่งจากสองวิธีที่อธิบายไว้ก่อนหน้านี้

นอกจากนี้ยังช่วยให้เข้าใจกลไกของกระบวนการอนุญาต:

  • เอ็กซ์ลูกค้า (เช่นโปรแกรมประยุกต์แบบ GUI) $DISPLAYที่ทำงานในภาชนะที่มีลักษณะในแฟ้มดิสเพลย์สำหรับรายการคุกกี้ที่ตรงกับชื่อโฮสต์คอนเทนเนอร์และความคุ้มค่าของ
  • หากพบรายการที่ตรงกันไคลเอ็นต์ X จะส่งผ่านด้วยคำร้องขอการอนุญาตไปยังเซิร์ฟเวอร์ X ผ่านซ็อกเก็ตที่เหมาะสมใน/tmp/.X11-unixไดเร็กทอรีที่เมาท์ในคอนเทนเนอร์

หมายเหตุ:ซ็อกเก็ต X11 Unix ยังคงต้องติดตั้งในคอนเทนเนอร์มิฉะนั้นคอนเทนเนอร์จะไม่มีเส้นทางไปยังเซิร์ฟเวอร์ X การกระจายส่วนใหญ่ปิดใช้งานการเข้าถึง TCP ไปยังเซิร์ฟเวอร์ X โดยค่าเริ่มต้นด้วยเหตุผลด้านความปลอดภัย

สำหรับข้อมูลเพิ่มเติมและเพื่อให้เข้าใจการทำงานของความสัมพันธ์ X ไคลเอนต์ / เซิร์ฟเวอร์ได้ดียิ่งขึ้นก็เป็นประโยชน์เช่นกันในการดูกรณีตัวอย่างของการส่งต่อ SSH X:

  • เซิร์ฟเวอร์ SSH ที่รันบนเครื่องระยะไกลจำลองเซิร์ฟเวอร์ X ของตนเอง
  • มันตั้งค่าของ$DISPLAYในเซสชั่น SSH ให้ชี้ไปที่ X server ของตัวเอง
  • มันใช้xauthเพื่อสร้างคุกกี้ใหม่สำหรับโฮสต์ระยะไกลและเพิ่มลงในXauthorityไฟล์สำหรับผู้ใช้ภายในและระยะไกล
  • เมื่อเริ่มแอพ GUI พวกเขาจะคุยกับเซิร์ฟเวอร์ X emulated ของ SSH
  • เซิร์ฟเวอร์ SSH ส่งต่อข้อมูลนี้กลับไปที่ไคลเอ็นต์ SSH บนเดสก์ท็อปท้องถิ่นของคุณ
  • ไคลเอ็นต์ SSH ในพื้นที่จะส่งข้อมูลไปยังเซสชันเซิร์ฟเวอร์ X ที่ทำงานบนเดสก์ท็อปของคุณราวกับว่าไคลเอ็นต์ SSH เป็นไคลเอ็นต์ X จริง ๆ (เช่นแอป GUI)
  • เซิร์ฟเวอร์ X ใช้ข้อมูลที่ได้รับเพื่อแสดง GUI บนเดสก์ท็อปของคุณ
  • ในตอนเริ่มต้นของการแลกเปลี่ยนนี้ไคลเอนต์ X ระยะไกลยังส่งคำขอการอนุญาตโดยใช้คุกกี้ที่เพิ่งสร้างขึ้น เซิร์ฟเวอร์ X โลคัลเปรียบเทียบกับสำเนาโลคัล

12

นี่ไม่ใช่น้ำหนักเบา แต่เป็นโซลูชันที่ดีที่ให้ความเท่าเทียมกันของคุณสมบัตินักเทียบเคียงกับการจำลองเสมือนบนเดสก์ท็อป ทั้ง Xfce4 หรือ IceWM สำหรับ Ubuntu และ CentOS ทำงานและnoVNCตัวเลือกนี้ทำให้สามารถเข้าถึงได้ง่ายผ่านเบราว์เซอร์

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

มันทำงานได้noVNCดีเท่ากับtigerVNCvncserver จากนั้นจะเรียกstartxใช้ Window Manager ที่กำหนด นอกจากนี้libnss_wrapper.soยังใช้เพื่อจำลองการจัดการรหัสผ่านสำหรับผู้ใช้


มีใครทดสอบหรือไม่
guilhermecgs

3
@guilhermecgs ใช่และทำงานได้ดี ตั้งแต่นั้นมาฉันก็ลองใช้ตัวxpraเทียบท่าซึ่งเป็น X-root ที่น้อยกว่าxpraนั้นเป็น IMO ที่เหมาะสมที่สุดและมีประสิทธิภาพมากกว่า VNC
dashesy

เพื่อให้ชัดเจน ... ฉันสามารถใช้เดสก์ท็อปเต็มรูปแบบ (GNOME, KDE) กับภาพนี้ได้หรือไม่
guilhermecgs

ฉันลองใช้ Xfce4 และ IceWM เท่านั้น (ซึ่งอยู่ใน repo นั้น) แน่นอนว่าประสบการณ์จะมี จำกัด ตัวอย่างเช่นอุปกรณ์ติดตั้งจะไม่ปรากฏในเดสก์ท็อป (gvfs) เว้นแต่ว่าคุณ--device /dev/...จะผ่านไปยังนักเทียบท่าและตั้งค่า--capสิทธิ์ที่จำเป็น นั่นเอาชนะวัตถุประสงค์ของการกักกัน แต่คุณสามารถผ่านอุปกรณ์ต่างๆได้ ด้วยการปรับแต่งมันควรจะเป็นไปได้ผมเชื่อว่ารัน GNOME / KDE ภายใต้ VNC ฉันใช้ X นักเทียบท่าพร้อมการ์ด nvidia (ไม่มี VNC หรือ Xpra) ดังนั้นจึงทำได้
dashesy

เราไม่ได้ลองมาก่อน ความท้าทายที่ยิ่งใหญ่ที่สุดในเรื่องนี้ก็คือการสร้าง D-Bus daemon ที่ทำงานได้ เดสก์ท็อป gnome หรือ KDE ส่วนใหญ่จะต้องการมัน ขอให้โครงการubuntu-desktop-lxde-vncช่วยคุณได้
toschneck

11

โซลูชันที่ให้ไว้ที่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/


3
ฉันพบว่าคุณไม่เคยแม้แต่จะผ่าน/tmp/.X11-unixเบ้าตาเลย มันก็ทำงานร่วมกับการติดตั้งและ.Xauthority --net=host
CMCDragonkai

2
นี่เป็นทางออกเดียวที่ใช้งานได้ในปัจจุบัน ใช้/tmp/.X11-unixเป็นปริมาณไม่ทำงานอีกต่อไปเป็นนักเทียบท่าเงียบปฏิเสธปริมาณเมานต์จากไดเรกทอรีเหนียว
Christian Hujer

1
ฉันคิดว่ามันขึ้นอยู่กับสิ่งที่คุณใช้ distro คุณสามารถเชื่อมต่อซ็อกเก็ต X11 Unix ได้อย่างแน่นอนบน CentOS สิ่งสำคัญคือต้องเข้าใจสิ่งที่--network=hostไม่ ช่วยให้คุณเข้าถึงคอนเทนเนอร์สแต็กเครือข่ายของโฮสต์ได้อย่างสมบูรณ์ซึ่งอาจไม่เป็นที่พึงปรารถนาทั้งนี้ขึ้นอยู่กับสิ่งที่คุณพยายามทำ หากคุณเพียงแค่เปิดใช้ GUI ที่มีคอนเทนเนอร์บนเดสก์ท็อปของคุณคุณก็ไม่ควรพลาด
orodbhen

7

มีโซลูชันอื่นโดย lord.garbageเพื่อเรียกใช้แอป GUI ในคอนเทนเนอร์โดยไม่ใช้การส่งต่อ VNC, SSH และ X11 มันถูกกล่าวถึงที่นี่ด้วย


1
นี่เป็นสิ่งที่ดีหากความปลอดภัยไม่ใช่เรื่องที่น่ากังวล หากจุดประสงค์ของการเชื่อมต่อบางสิ่งเพื่อแยกมันเป็นวิธีที่ดีที่สุดที่จะหลีกเลี่ยง X11 ที่เข้ามาในภาชนะ
จะ

7

หากคุณต้องการที่จะเรียกใช้โปรแกรมประยุกต์แบบ GUI หัวขาดแล้วอ่านที่นี่ สิ่งที่คุณต้องทำคือการสร้างจอภาพเสมือนด้วยxvfbหรือซอฟต์แวร์อื่นที่คล้ายคลึงกัน สิ่งนี้มีประโยชน์มากหากคุณต้องการเรียกใช้การทดสอบซีลีเนียมกับเบราว์เซอร์

สิ่งที่ไม่ได้กล่าวถึงคือซอฟต์แวร์บางตัวใช้ Sand-Boxing กับตู้คอนเทนเนอร์ Linux ตัวอย่างเช่น Chrome จะไม่ทำงานตามปกติหากคุณไม่ใช้การตั้งค่าสถานะที่เหมาะสม--privilegedเมื่อเรียกใช้คอนเทนเนอร์


6

ฉันสายไปงานเลี้ยง แต่สำหรับผู้ใช้ 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 ที่เชื่อมโยงเพื่อสร้างและเรียกใช้คำสั่งหากคุณต้องการ / ต้องการ


5

จากคำตอบของ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 โดยอัตโนมัติทุกครั้งที่ระบบรีสตาร์ทและลงชื่อเข้าใช้ของผู้ใช้


4

โซลูชั่นอื่น ๆ ควรจะทำงาน 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

3

สำหรับการเรนเดอร์ OpenGL ด้วยไดรเวอร์ Nvidia ให้ใช้ภาพต่อไปนี้:

https://github.com/thewtex/docker-opengl-nvidia

สำหรับการใช้งาน OpenGL อื่น ๆ ตรวจสอบให้แน่ใจว่าภาพมีการนำไปปฏิบัติเช่นเดียวกับโฮสต์


3

คุณสามารถอนุญาตให้ผู้ใช้ 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

2

OSX (10.13.6, เทือกเขาสูง)

คล้ายกับคำตอบของ@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 จากคอนเทนเนอร์นักเทียบท่าเดเบียนของฉันได้เช่นกัน


1

นักเทียบท่าพร้อมเครือข่าย 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

1

อีกคำตอบหนึ่งในกรณีที่คุณสร้างภาพ:

  1. เรียกใช้ตัวเทียบท่าที่ไม่มี sudo ( วิธีแก้ไขตัวเทียบท่า: มีปัญหาถูกปฏิเสธสิทธิ์ )

  2. แชร์ USER & home & passwd เดียวกันระหว่างโฮสต์และคอนเทนเนอร์แชร์ (เคล็ดลับ: ใช้รหัสผู้ใช้แทนชื่อผู้ใช้)

  3. โฟลเดอร์ dev สำหรับ libs ที่ขึ้นอยู่กับไดรเวอร์ให้ทำงานได้ดี

  4. บวก 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 )

ดังนั้นการใช้งานประเภทนี้จึงเหมาะสำหรับนักพัฒนาที่ฉันคิดว่า


นี่เป็นสิ่งเดียวที่จะทำงานให้ฉันได้ สำหรับจุดประสงค์ของฉันฉันสามารถย่อให้เหลือขนาดนี้ได้: นักเทียบท่าวิ่ง --network = host --volume = echo ~: / home / $ {USER} --user = id -u ${USER}--env = "DISPLAY" --volume = "/ etc / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
user1145922

1

ฉันจัดการเพื่อเรียกใช้การสตรีมวิดีโอจากกล้อง USB ที่ใช้opencvในการdockerทำตามขั้นตอนเหล่านี้:

  1. ให้นักเทียบท่าเข้าถึงเซิร์ฟเวอร์ X

    xhost +local:docker
    
  2. สร้างซ็อกเก็ต X11 Unix และไฟล์การพิสูจน์ตัวตน X

    XSOCK=/tmp/.X11-unix
    XAUTH=/tmp/.docker.xauth
    
  3. เพิ่มสิทธิ์ที่เหมาะสม

    xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
    
  4. ตั้งค่าความเร็วในการเรนเดอร์ Qt เป็น "เนทีฟ" ดังนั้นจึงไม่ข้าม X11 เอ็นจิ้นการเรนเดอร์

    export QT_GRAPHICSSYSTEM=native
    
  5. บอก Qt ว่าอย่าใช้ MIT-SHM (หน่วยความจำที่ใช้ร่วมกัน) - วิธีนี้ควรปลอดภัยกว่าด้วยเช่นกัน

    export QT_X11_NO_MITSHM=1
    
  6. อัพเดตคำสั่ง 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


"สร้างซ็อกเก็ต X11 Unix และไฟล์การรับรองความถูกต้อง X" ไม่ได้สร้างไฟล์ใด ๆ มันแค่กำหนดตัวแปรหรือไม่?
MrR
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.