Làm thế nào bạn có thể chạy các ứng dụng GUI trong một Docker container?
Có bất kỳ hình ảnh nào được thiết lập vncserver
hoặc một cái gì đó để bạn có thể - ví dụ - thêm một hộp cát tăng tốc xung quanh nói Firefox không?
Làm thế nào bạn có thể chạy các ứng dụng GUI trong một Docker container?
Có bất kỳ hình ảnh nào được thiết lập vncserver
hoặc một cái gì đó để bạn có thể - ví dụ - thêm một hộp cát tăng tốc xung quanh nói Firefox không?
Câu trả lời:
Bạn chỉ có thể cài đặt một vncserver cùng với Firefox :)
Tôi đã đẩy một hình ảnh, vnc / firefox, ở đây: docker pull creack/firefox-vnc
Hình ảnh đã được thực hiện với Dockerfile này:
# 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'
Điều này sẽ tạo ra một Docker container chạy VNC với mật khẩu 1234
:
Đối với Docker phiên bản 18 hoặc mới hơn:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Đối với Docker phiên bản 1.3 trở lên:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Đối với Docker trước phiên bản 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
docker inspect <container id>
hoặc đơn giản docker ps
, sau đó bạn kết nối với ip của máy chủ lưu trữ với cổng bạn vừa tìm thấy.
Xauthority trở thành một vấn đề với các hệ thống mới hơn. Tôi có thể loại bỏ bất kỳ sự bảo vệ nào với xhost + trước khi chạy các container docker của mình hoặc tôi có thể chuyển vào một tệp Xauthority được chuẩn bị tốt. Các tập tin Xauthority điển hình là tên máy chủ cụ thể. Với docker, mỗi container có thể có một tên máy chủ khác nhau (được đặt với docker run -h), nhưng ngay cả việc đặt tên máy chủ của container giống với hệ thống máy chủ cũng không giúp ích gì trong trường hợp của tôi. xeyes (tôi thích ví dụ này) đơn giản là sẽ bỏ qua cookie ma thuật và không chuyển thông tin đăng nhập đến máy chủ. Do đó, chúng tôi nhận được thông báo lỗi 'Không có giao thức được chỉ định Không thể hiển thị mở'
Tệp Xauthority có thể được viết theo cách để tên máy chủ không quan trọng. Chúng ta cần đặt Gia đình xác thực thành 'FamilyWild'. Tôi không chắc chắn, nếu xauth có một dòng lệnh thích hợp cho việc này, vì vậy đây là một ví dụ kết hợp xauth và sed để làm điều đó. Chúng ta cần thay đổi 16 bit đầu tiên của đầu ra danh sách. Giá trị của FamilyWild là 65535 hoặc 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
có thể rút ngắn thành-v $XSOCK -v $XAUTH
:0
bằng $DISPLAY
. Điều đó có nghĩa là xauth nlist $DISPLAY | ...
và docker run -ti -e DISPLAY=$DISPLAY ...
. Thông thường X HIỂN THỊ là :0
, nhưng không phải luôn luôn (và đặc biệt là không nếu bạn đang kết nối qua ssh -X).
/tmp/.docker.xauth
tệp có 600
quyền. Điều này dẫn đến xauth bên trong container docker không thể đọc tệp. Bạn có thể xác minh bằng cách chạy xauth list
trong container docker. Tôi đã thêm chmod 755 $XAUTH
sau xauth nlist :0 | ...
lệnh để giải quyết điều này.
Tôi chỉ tìm thấy mục blog này và muốn chia sẻ nó ở đây với bạn bởi vì tôi nghĩ đó là cách tốt nhất để làm điều đó và nó rất dễ dàng.
http://fabiorehm.com/blog/2014/09/11/rucky-gui-apps-with-docker/
PROS:
+ không có công cụ máy chủ x trong bộ chứa docker
+ không cần máy khách / máy chủ vnc
+ không có ssh với x chuyển tiếp
+ bộ chứa docker nhỏ hơn nhiều
Nhược điểm:
- sử dụng x trên máy chủ (không có nghĩa là hộp cát an toàn)
trong trường hợp liên kết sẽ thất bại một ngày nào đó tôi đã đặt phần quan trọng nhất ở đây:
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
xây dựng hình ảnh:
docker build -t firefox .
và lệnh chạy:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
Tất nhiên bạn cũng có thể làm điều này trong lệnh chạy với sh -c "echo script-here"
GỢI Ý: để biết âm thanh, hãy xem: https://stackoverflow.com/a/28985715/2835523
apt-get -y install sudo
để tạo /etc/sudoers.d
thư mục.
$ xhost +
Với khối lượng dữ liệu docker, rất dễ dàng để lộ ổ cắm miền unix của xorg bên trong container.
Ví dụ: với Dockerfile như thế này:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
Bạn có thể làm như sau:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
Tất nhiên điều này về cơ bản giống như chuyển tiếp X. Nó cấp cho bộ chứa toàn quyền truy cập vào xserver trên máy chủ, vì vậy chỉ nên sử dụng nếu bạn tin tưởng những gì bên trong.
Lưu ý: Nếu bạn lo ngại về bảo mật, một giải pháp tốt hơn sẽ là giới hạn ứng dụng với điều khiển truy cập bắt buộc hoặc dựa trên vai trò . Docker đạt được sự cô lập khá tốt, nhưng nó được thiết kế với mục đích khác. Sử dụng AppArmor , SELinux hoặc GrSecurity , được thiết kế để giải quyết mối quan tâm của bạn.
xhost +
trên máy chủ.
xhost +local
là cần thiết. ~/.Xauthority
Tuy nhiên, tốt hơn là làm cho tệp có sẵn trong vùng chứa, vì vậy nó có thể tự xác thực.
Can't open display: :0
. Có ý kiến gì không?
xhost +si:localuser:$USER
để ủy quyền chỉ người dùng bắt đầu container.
Bạn cũng có thể sử dụng người dùng phụ: https://github.com/timthelion/subuser
Điều này cho phép bạn đóng gói nhiều ứng dụng gui trong docker. Firefox và emacs đã được thử nghiệm cho đến nay. Với firefox, webGL không hoạt động. Chromium hoàn toàn không hoạt động.
EDIT: Âm thanh hoạt động!
EDIT2: Trong thời gian kể từ lần đầu tiên tôi đăng bài này, người đăng ký đã tiến bộ rất nhiều. Bây giờ tôi có một trang web lên subuser.org và một mô hình bảo mật mới để kết nối với X11 thông qua cầu nối XPRA .
Jürgen Weigert có câu trả lời tốt nhất phù hợp với tôi trên Ubuntu, tuy nhiên trên OSX, docker chạy bên trong VirtualBox và vì vậy giải pháp không hoạt động mà không cần làm việc thêm.
Tôi đã làm cho nó hoạt động với các thành phần bổ sung này:
Tôi đánh giá cao ý kiến của người dùng để cải thiện câu trả lời này cho OSX, tôi không chắc liệu chuyển tiếp ổ cắm cho X có an toàn không, nhưng mục đích sử dụng của tôi chỉ dành cho việc chạy bộ chứa docker cục bộ.
Ngoài ra, tập lệnh hơi mong manh ở chỗ không dễ lấy địa chỉ IP của máy vì nó không dây cục bộ của chúng tôi nên luôn có một số IP ngẫu nhiên.
Kịch bản BASH tôi sử dụng để khởi chạy container:
#!/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
Tôi có thể khiến xeyes và matplotlib hoạt động với phương pháp này.
Nó dễ dàng hơn một chút trên Windows 7+ với 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.
và Error: cannot open display: VAIO:0.0
. Bạn đã gặp một cái gì đó như thế này?
Chia sẻ hiển thị máy chủ: 0, như đã nêu trong một số câu trả lời khác, có hai nhược điểm:
xev
hoặc xinput
có thể, và điều khiển từ xa các ứng dụng máy chủ với xdotool
.--ipc=host
).Bên dưới một tập lệnh mẫu để chạy một hình ảnh docker trong Xephyr giải quyết vấn đề này.
--cap-drop ALL --security-opt no-new-privileges
. Ngoài ra người dùng container không root.Kịch bản dự kiến một số đối số, đầu tiên là trình quản lý cửa sổ máy chủ chạy trong Xephyr, thứ hai là hình ảnh docker, tùy chọn thứ ba một lệnh hình ảnh sẽ được thực thi. Để chạy môi trường máy tính để bàn trong docker, hãy sử dụng ":" thay vì trình quản lý cửa sổ máy chủ.
Đóng cửa sổ Xephyr chấm dứt các ứng dụng container docker. Chấm dứt các ứng dụng được neo sẽ đóng cửa sổ Xephyr.
Ví dụ:
xephyrdocker "openbox --sm-disable" x11docker/lxde pcmanfm
xephyrdocker : x11docker/lxde
xephyrdocker xfwm4 --device /dev/snd jess/nes /games/zelda.rom
tập lệnh 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
Kịch bản này được duy trì tại wiki x11docker . Một tập lệnh nâng cao hơn là x11docker cũng hỗ trợ các tính năng như tăng tốc GPU, chia sẻ webcam và máy in, v.v.
Đây là một giải pháp gọn nhẹ mà tránh phải cài đặt bất kỳ X
máy chủ, vnc
máy chủ hoặc sshd
trình nền nào trên container. Những gì nó đạt được trong sự đơn giản, nó mất đi sự an toàn và cô lập.
Nó giả định rằng bạn kết nối với máy chủ sử dụng ssh
với X11
chuyển tiếp.
Trong sshd
cấu hình của máy chủ, thêm dòng
X11UseLocalhost no
Vì vậy, cổng máy chủ X được chuyển tiếp trên máy chủ được mở trên tất cả các giao diện (không chỉ lo
) và đặc biệt trên giao diện ảo Docker , docker0
.
Container, khi chạy, cần truy cập vào .Xauthority
tệp để nó có thể kết nối với máy chủ. Để làm điều đó, chúng tôi xác định một ổ đĩa chỉ đọc vào thư mục chính trên máy chủ (có thể không phải là một ý tưởng khôn ngoan!) Và cũng đặt XAUTHORITY
biến tương ứng.
docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority
Điều đó là không đủ, chúng tôi cũng phải chuyển biến HIỂN THỊ từ máy chủ lưu trữ, nhưng thay thế tên máy chủ bằng ip:
-e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")
Chúng ta có thể định nghĩa một bí danh:
alias dockerX11run='docker run -v $HOME:/hosthome:ro -e XAUTHORITY=/hosthome/.Xauthority -e DISPLAY=$(echo $DISPLAY | sed "s/^.*:/$(hostname -i):/")'
Và kiểm tra nó như thế này:
dockerX11run centos xeyes
.Xauthority
tệp : -v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
.
X11UseLocalhost
, bạn cũng có thể sử dụng tùy chọn bổ sung --net=host
cho docker run
lệnh (tìm thấy ở đây ).
--net=host
là một ý tưởng tồi vì bây giờ nếu bạn mở một cổng trong container thì nó cũng sẽ được mở trong máy chủ ...
Mặc dù câu trả lời của Jürgen Weigert về cơ bản bao gồm giải pháp này, ban đầu tôi không rõ ràng về những gì được mô tả ở đó. Vì vậy, tôi sẽ thêm nhận của tôi về nó, trong trường hợp bất cứ ai khác cần làm rõ.
Off đầu tiên, các tài liệu có liên quan là manpage X an ninh .
Nhiều nguồn trực tuyến đề nghị chỉ cần gắn ổ cắm unix X11 và ~/.Xauthority
tệp vào thùng chứa. Các giải pháp này thường hoạt động một cách may mắn, mà không thực sự hiểu lý do tại sao, ví dụ: người dùng container kết thúc với cùng UID với người dùng, do đó không cần ủy quyền khóa ma thuật.
Trước hết, tệp Xauthority có chế độ 0600, vì vậy người dùng container sẽ không thể đọc được trừ khi có cùng UID.
Ngay cả khi bạn sao chép tệp vào vùng chứa và thay đổi quyền sở hữu, vẫn còn một vấn đề khác. Nếu bạn chạy xauth list
trên máy chủ và vùng chứa, với cùng một Xauthority
tệp, bạn sẽ thấy các mục khác nhau được liệt kê. Điều này là do xauth
lọc các mục tùy thuộc vào nơi nó chạy.
Máy khách X trong vùng chứa (tức là ứng dụng GUI) sẽ hoạt động giống như xauth
. Nói cách khác, nó không thấy cookie ma thuật cho phiên X chạy trên máy tính để bàn của người dùng. Thay vào đó, nó nhìn thấy các mục cho tất cả các phiên X "từ xa" mà bạn đã mở trước đó (giải thích bên dưới).
Vì vậy, những gì bạn cần làm là thêm một mục mới với tên máy chủ của container và cùng một khóa hex với cookie máy chủ (tức là phiên X đang chạy trên máy tính để bàn của bạn), ví dụ:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
Điều hấp dẫn là cookie phải được thêm vào xauth add
bên trong thùng chứa:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Mặt khác, xauth
gắn thẻ nó theo cách mà nó chỉ nhìn thấy bên ngoài container.
Định dạng cho lệnh này là:
xauth add hostname/$DISPLAY protocol hexkey
Trường hợp .
đại diện cho MIT-MAGIC-COOKIE-1
giao thức.
Lưu ý: Không cần phải sao chép hoặc gắn kết .Xauthority
vào container. Chỉ cần tạo một tập tin trống, như được hiển thị, và thêm cookie.
Câu trả lời của Jürgen Weigert giải quyết vấn đề này bằng cách sử dụng FamilyWild
loại kết nối để tạo một tệp ủy quyền mới trên máy chủ và sao chép nó vào thùng chứa. Lưu ý rằng trước tiên, nó trích xuất khóa hex cho phiên X hiện tại ~/.Xauthority
sử dụng xauth nlist
.
Vì vậy, các bước cần thiết là:
FamilyWild
loại kết nối).Tôi thừa nhận rằng tôi không hiểu rõ về cách thức FamilyWild
hoạt động hoặc cách thức xauth
hoặc các ứng dụng khách X lọc các mục từ tệp Xauthority tùy thuộc vào nơi chúng chạy. Thông tin bổ sung về điều này được chào đón.
Nếu bạn muốn phân phối ứng dụng Docker của mình, bạn sẽ cần một tập lệnh khởi động để chạy bộ chứa lấy khóa hex cho phiên X của người dùng và nhập nó vào bộ chứa theo một trong hai cách đã giải thích trước đây.
Nó cũng giúp hiểu được các cơ chế của quy trình ủy quyền:
$DISPLAY
./tmp/.X11-unix
thư mục được gắn trong thùng chứa.Lưu ý: Ổ cắm Unix X11 vẫn cần được gắn trong bộ chứa, hoặc bộ chứa sẽ không có tuyến đường đến máy chủ X. Hầu hết các bản phân phối vô hiệu hóa quyền truy cập TCP vào máy chủ X theo mặc định vì lý do bảo mật.
Để biết thêm thông tin và để hiểu rõ hơn cách thức hoạt động của mối quan hệ máy khách / máy chủ X, bạn cũng nên xem xét trường hợp ví dụ về chuyển tiếp SSH X:
$DISPLAY
trong phiên SSH để trỏ đến máy chủ X của chính nó.xauth
để tạo cookie mới cho máy chủ từ xa và thêm nó vào các Xauthority
tệp cho cả người dùng cục bộ và người dùng từ xa.Đây không phải là trọng lượng nhẹ nhưng là một giải pháp tốt mang lại tính năng tương đương cho docker với ảo hóa máy tính để bàn đầy đủ. Cả Xfce4 hoặc IceWM cho Ubuntu và CentOS đều hoạt động và noVNC
tùy chọn này giúp truy cập dễ dàng thông qua trình duyệt.
https://github.com/ConSol/docker-headless-vnc-container
Nó chạy noVNC
cũng như tigerVNC
vncserver. Sau đó, nó gọi startx
cho Trình quản lý cửa sổ nhất định. Ngoài ra, libnss_wrapper.so
được sử dụng để giả lập quản lý mật khẩu cho người dùng.
xpra
trong docker, đó là root X. không phải xpra
là IMO phù hợp nhất và hiệu quả hơn VNC.
--device /dev/...
đến docker và đặt các --cap
đặc quyền cần thiết . Điều đó đánh bại mục đích ngăn chặn, nhưng bạn có thể đi qua các thiết bị. Với một số điều chỉnh, có thể tôi tin rằng sẽ chạy Gnome / KDE theo VNC. Tôi đã chạy nhiều X trong docker với thẻ nvidia (không có VNC hoặc Xpra), vì vậy điều đó chắc chắn là có thể thực hiện được.
Giải pháp được đưa ra tại http://fabiorehm.com/blog/2014/09/11/rasty-gui-apps-with-docker/ dường như là một cách dễ dàng để bắt đầu các ứng dụng GUI từ bên trong các thùng chứa (Tôi đã thử dùng firefox trên Ubuntu 14.04) nhưng tôi thấy rằng cần phải có một thay đổi nhỏ đối với giải pháp được đăng bởi tác giả.
Cụ thể, để chạy container, tác giả đã đề cập:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
Nhưng tôi thấy rằng (dựa trên một nhận xét cụ thể trên cùng một trang) rằng hai tùy chọn bổ sung
-v $HOME/.Xauthority:$HOME/.Xauthority
và
-net=host
cần được chỉ định trong khi chạy container để firefox hoạt động bình thường:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $HOME/.Xauthority:$HOME/.Xauthority \
-net=host \
firefox
Tôi đã tạo một hình ảnh docker với thông tin trên trang đó và những phát hiện bổ sung này: https://hub.docker.com/r/amanral/ub Ubuntu-firefox /
/tmp/.X11-unix
ổ cắm. Nó chỉ hoạt động với gắn kết .Xauthority
và --net=host
.
/tmp/.X11-unix
như âm lượng không còn hoạt động, vì docker âm thầm từ chối gắn kết âm lượng từ các thư mục dính.
--network=host
làm. Nó cung cấp cho container của bạn toàn quyền truy cập vào ngăn xếp mạng của máy chủ, điều này có thể không mong muốn, tùy thuộc vào những gì bạn đang cố gắng thực hiện. Nếu bạn chỉ mày mò với việc chạy GUI được đóng gói trên máy tính để bàn của mình, thì điều đó không thành vấn đề.
Có một giải pháp khác của lord.garbage để chạy các ứng dụng GUI trong một container mà không cần sử dụng chuyển tiếp VNC, SSH và X11. Nó được đề cập ở đây quá.
Nếu bạn muốn chạy một ứng dụng GUI không đầu, thì hãy đọc ở đây . Những gì bạn phải làm là tạo ra một màn hình ảo bằng xvfb
hoặc phần mềm tương tự khác. Điều này rất hữu ích nếu bạn muốn chạy thử nghiệm Selenium chẳng hạn với các trình duyệt.
Một cái gì đó không được đề cập ở bất cứ đâu là một số phần mềm thực sự sử dụng sand-boxing với các thùng chứa Linux. Vì vậy, ví dụ Chrome sẽ không bao giờ chạy bình thường nếu bạn không sử dụng cờ thích hợp --privileged
khi chạy container.
Tôi đến bữa tiệc muộn, nhưng với những người dùng Mac không muốn đi theo con đường XQuartz, đây là một ví dụ hoạt động xây dựng Fedora Image, với Môi trường máy tính để bàn (xfce) bằng cách sử dụng Xvfb
và VNC
. Thật đơn giản và hiệu quả:
Trên máy Mac, bạn chỉ có thể truy cập bằng ứng dụng Chia sẻ màn hình (mặc định), kết nối với 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"]
bắt đầu-vc.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
Kiểm tra readme được liên kết để xây dựng và chạy các lệnh nếu bạn muốn / cần.
Dựa trên câu trả lời của Jürgen Weigert , tôi có một số cải tiến:
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
Sự khác biệt duy nhất là nó tạo một thư mục $ XAUTH_DIR, được sử dụng để đặt tệp $ XAUTH và gắn thư mục $ XAUTH_DIR thay vì tệp $ XAUTH vào thùng chứa docker.
Lợi ích của phương pháp này là bạn có thể viết một lệnh trong /etc/rc.local để tạo một thư mục trống có tên $ XAUTH_DIR trong / tmp và thay đổi chế độ của nó thành 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
Khi hệ thống khởi động lại, trước khi người dùng đăng nhập, docker sẽ tự động gắn thư mục $ XAUTH_DIR nếu chính sách khởi động lại của container là "luôn luôn". Sau khi người dùng đăng nhập, bạn có thể viết một lệnh trong ~ / .profile để tạo tệp $ XAUTH, sau đó bộ chứa sẽ tự động sử dụng tệp $ XAUTH này.
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
Sau đó, container sẽ tự động lấy tệp Xauthority mỗi khi hệ thống khởi động lại và người dùng đăng nhập.
Các giải pháp khác nên hoạt động, nhưng đây là một giải pháp cho docker-compose
.
Để khắc phục lỗi đó, bạn cần chuyển $ HIỂN THỊ và .X11-unix cho docker, cũng như cấp cho người dùng bắt đầu truy cập docker vào xhost.
Trong docker-compose.yml
tập tin:
version: '2'
services:
node:
build: .
container_name: node
environment:
- DISPLAY
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
Trong thiết bị đầu cuối hoặc tập lệnh:
xhost +si:localuser:$USER
xhost +local:docker
export DISPLAY=$DISPLAY
docker-compose up
Để hiển thị OpenGL với trình điều khiển Nvidia, hãy sử dụng hình ảnh sau:
https://github.com/thewtex/docker-opengl-nvidia
Đối với các triển khai OpenGL khác, hãy đảm bảo hình ảnh có cùng triển khai với máy chủ.
Tương tự như câu trả lời của @Nick , nhưng giải pháp của anh ấy không hiệu quả với tôi.
Trước tiên hãy cài đặt socat bằng cách thực hiện brew install socat
và cài đặt XQuartz ( https://www.xquartz.org/ )
Sau đó, làm theo các bước sau tại đây ( http://fabiorehm.com/blog/2014/09/11/rasty-gui-apps-with-docker/ ) trong phần bình luận:
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
Tôi cũng có thể khởi chạy CLion từ container docker debian của mình.
Docker với mạng CẦU. cho Ubuntu 16.04 với lightdm của trình quản lý hiển thị:
cd /etc/lightdm/lightdm.conf.d
sudo nano user.conf
[Seat:*]
xserver-allow-tcp=true
xserver-command=X -listen tcp
bạn có thể sử dụng nhiều quyền riêng tư hơn
xhost +
docker run --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --env="DISPLAY=$HOST_IP_IN_BRIDGE_NETWORK:0" --net=bridge $container_name
Một câu trả lời khác trong trường hợp bạn đã xây dựng hình ảnh:
gọi docker w / o sudo ( Cách sửa docker: Có sự cố từ chối quyền )
chia sẻ cùng NGƯỜI DÙNG & nhà & mật khẩu giữa máy chủ và chia sẻ vùng chứa (mẹo: sử dụng id người dùng thay vì tên người dùng)
thư mục dev cho libs trình điều khiển phụ thuộc để hoạt động tốt
cộng X11 về phía trước.
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
bạn có thể hỏi, điểm quan trọng của việc sử dụng docker là gì nếu có quá nhiều thứ giống nhau? tốt, một lý do tôi có thể nghĩ đến là vượt qua địa ngục phụ thuộc gói ( https://en.wikipedia.org/wiki/Dependency_hell ).
Vì vậy, loại sử dụng này phù hợp hơn cho nhà phát triển tôi nghĩ.
echo ~
: / home / $ {USER} --user = id -u ${USER}
--env = "HIỂN THỊ" --volume = "/ etc / passwd: / etc / passwd: ro "-it REPO: TAG / bin / bash
Tôi quản lý để chạy một dòng video từ camera USB sử dụng opencv
trong docker
bằng cách làm theo các bước sau:
Cho phép docker truy cập máy chủ X
xhost +local:docker
Tạo ổ cắm Unix X11 và tệp xác thực X
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
Thêm quyền thích hợp
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
Đặt tốc độ kết xuất Qt thành "gốc", do đó, nó không bỏ qua công cụ kết xuất X11
export QT_GRAPHICSSYSTEM=native
Nói với Qt không sử dụng MIT-SHM (bộ nhớ dùng chung) - theo cách đó cũng sẽ an toàn hơn về bảo mật
export QT_X11_NO_MITSHM=1
Cập nhật lệnh chạy 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
Lưu ý: Khi bạn hoàn thành dự án, hãy trả về các điều khiển truy cập ở giá trị mặc định của chúng - xhost -local:docker
Thêm chi tiết: Sử dụng GUI với Docker
Tín dụng: Phát hiện đối tượng xử lý video và thời gian thực bằng cách sử dụng Tensorflow, OpenCV và Docker