Як можна запускати програми GUI в контейнері Docker ?
Чи є якісь зображення, які налаштовані, vncserver
або щось таке, що ви можете, наприклад, додати додаткову пісочну скриньку швидкості навколо, наприклад, Firefox?
Як можна запускати програми GUI в контейнері Docker ?
Чи є якісь зображення, які налаштовані, vncserver
або щось таке, що ви можете, наприклад, додати додаткову пісочну скриньку швидкості навколо, наприклад, 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
Для Докер версії 1.3 або новішої:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
Для Docker до версії 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
docker inspect <container id>
або просто docker ps
, потім ви підключитесь до ip хоста за допомогою щойно знайденого порту.
Xauthority стає проблемою з більш новими системами. Я можу зняти будь-який захист за допомогою xhost + перед тим, як запустити контейнери докера, або можу передати добре підготовлений файл Xauthority. Типові файли Xauthority залежать від імені хоста. За допомогою докера кожен контейнер може мати інше ім'я хоста (встановлений за допомогою докерного запуску -h), але навіть встановлення імені хоста контейнера, ідентичного хост-системі, не допомогло в моєму випадку. xeyes (мені подобається цей приклад) просто ігнорує чарівне файли cookie та не передасть серверні дані. Отже, ми отримуємо повідомлення про помилку "Не вказано протокол Неможливо відкрити дисплей"
Файл 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 всередині контейнера докера не може прочитати файл. Ви можете перевірити, запустивши xauth list
в контейнер докер. Я додав chmod 755 $XAUTH
після xauth nlist :0 | ...
команди, щоб вирішити цю проблему.
Я щойно знайшов цей запис у блозі і хочу поділитися ним з вами, тому що я думаю, що це найкращий спосіб зробити це, і це так просто.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
PROS:
+ відсутність x серверних даних у контейнері docker
+ не потрібен клієнт / сервер vnc
+ відсутність ssh з x переадресацією
+ значно менші контейнери докера
CONS:
- використання 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 +
З томами даних докера дуже просто викрити розетку домену xorg unix всередині контейнера.
Наприклад, із таким 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. Він надає контейнеру повний доступ до xserver на хості, тому рекомендується лише якщо ви довіряєте тому, що знаходиться всередині.
Примітка. Якщо ви стурбовані безпекою, кращим рішенням буде обмежити програму обов'язковим контролем доступу або на основі ролі . Докер здобув досить гарну ізоляцію, але він був розроблений з іншою метою. Використовуйте AppArmor , SELinux або GrSecurity , які були розроблені для вирішення ваших проблем.
xhost +
хост.
xhost +local
потрібно. ~/.Xauthority
Однак було б краще зробити файл доступним у контейнері, щоб він міг пройти автентифікацію.
Can't open display: :0
. Будь-які ідеї?
xhost +si:localuser:$USER
дозволяв користувачеві запускати контейнер.
Ви також можете використовувати субпользователя: https://github.com/timthelion/subuser
Це дозволяє упакувати багато додатків gui в докер. Firefox та emacs пройшли перевірку. З Firefox webGL не працює. Хром взагалі не працює.
EDIT: Звук працює!
EDIT2: За час, коли я вперше опублікував це, підопічний користувач сильно прогресував. Зараз у мене є веб-сайт subuser.org та нова модель безпеки для підключення до X11 через мостику XPRA .
Юрген Вейгерт має найкращу відповідь, яка працювала на мене на 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
. Також користувач контейнера не має root.Сценарій очікує деяких аргументів: перший менеджер вікон хоста запускається в Xephyr, другий зображення докера, необов'язково третій команда зображення, яка буде виконана. Щоб запустити середовище робочого столу в docker, використовуйте ":" замість менеджера вікон хоста.
Закриття вікна 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, який також підтримує такі функції, як прискорення графічного процесора, обмін веб-камерами та принтерами тощо.
Ось легке рішення, яке дозволяє уникнути встановлення будь-якого X
сервера, vnc
сервера чи sshd
демона на контейнері. Що отримує у простоті, воно втрачає у захисті та ізоляції.
Він передбачає, що ви підключаєтесь до хост-машини за ssh
допомогою X11
переадресації.
У sshd
конфігурації хоста додайте рядок
X11UseLocalhost no
Так що пересилається порт сервера X на хості відкритий для всіх інтерфейсів (не тільки 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
це погана ідея, як зараз, якщо ви відкриєте порт у контейнері, він буде відкритий і в хості ...
Хоча відповідь Юргена Вайгерта по суті стосується цього рішення, мені спочатку було не ясно, що там описано. Тож я додам свою справу, якщо хтось ще потребує роз'яснення.
По-перше, відповідна документація - це сторінка X безпеки .
Численні Інтернет-джерела пропонують просто встановити сокет X11 і ~/.Xauthority
файл в контейнер. Ці рішення часто працюють випадково, не розуміючи, чому, наприклад, користувач контейнера закінчується тим самим UID, що і користувач, тому немає необхідності в авторизації магічних ключів.
По-перше, файл Xauthority має режим 0600, тому користувач контейнера не зможе його прочитати, якщо у нього не буде однакового UID.
Навіть якщо ви скопіюєте файл у контейнер та зміните право власності, є ще одна проблема. Якщо ви працюєте xauth list
на хості та контейнері, з одним і тим же Xauthority
файлом, ви побачите в списку різні записи. Це тому, що xauth
фільтрує записи залежно від місця її запуску.
Клієнт X у контейнері (тобто GUI-додаток) поводитиметься так само, як і xauth
. Іншими словами, він не бачить чарівного файлу cookie для сесії X, що працює на робочому столі користувача. Натомість він бачить записи для всіх «віддалених» X сесій, які ви відкрили раніше (пояснено нижче).
Отже, що вам потрібно зробити, це додати новий запис із назвою хоста контейнера і тим же шістнадцятковим ключем, що і cookie хоста (тобто X сеанс, що працює на вашому робочому столі), наприклад:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
Проблема полягає в тому, що файл cookie потрібно додати xauth add
всередину контейнера:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
В іншому випадку xauth
позначає його тегом, щоб його бачили лише поза контейнером.
Формат для цієї команди такий:
xauth add hostname/$DISPLAY protocol hexkey
Де .
представлений MIT-MAGIC-COOKIE-1
протокол.
Примітка. Немає необхідності копіювати або прив’язувати .Xauthority
до контейнера. Просто створіть порожній файл, як показано, і додайте файл cookie.
Відповідь Юргена Вайгерта вирішує це за допомогою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-сервер.xauth
для створення нового файлу cookie для віддаленого хоста та додає його до Xauthority
файлів як для місцевих, так і віддалених користувачів.Це не мало ваги, але це приємне рішення, яке надає паритету функції докера повну віртуалізацію робочого столу. І Xfce4, або IceWM для Ubuntu і CentOS працюють, і цей noVNC
варіант дозволяє легко отримати доступ через браузер.
https://github.com/ConSol/docker-headless-vnc-container
Він працює noVNC
так само, як tigerVNC
і vncserver 's. Потім він вимагає startx
отримання відповідного менеджера вікон. Крім того, libnss_wrapper.so
використовується для імітації керування паролями для користувачів.
xpra
у докер, який не має коренів X. 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
робить. Це надає вашому контейнеру повний доступ до мережевого стека хоста, що може бути небажаним, залежно від того, що ви намагаєтеся зробити. Якщо ви просто розмовляєте із запуском контейнерних графічних інтерфейсів на робочому столі, це не має значення.
Існує ще одне рішення від lord.garbage для запуску програм GUI в контейнері без використання VNC, SSH та X11 переадресації. Він згадується тут теж.
Якщо ви хочете запустити програму GUI без голови, прочитайте тут . Що вам потрібно зробити, це створити віртуальний монітор з xvfb
іншим подібним програмним забезпеченням. Це дуже корисно, якщо ви хочете запустити тести Selenium, наприклад, із браузерами.
Щось ніде не згадується, це те, що деякі програми насправді самі використовують піщані бокси з контейнерами Linux. Так, наприклад, Chrome ніколи не працюватиме нормально, якщо ви не використовуєте відповідний прапор --privileged
під час запуску контейнера.
Я запізнився на вечірку, але для користувачів Mac , які не хочуть йти по шляху XQuartz, ось робочий приклад , який будує Fedora Image з Desktop Environment (XFCE) , використовуючи Xvfb
і VNC
. Це просто, і працює:
На Mac, ви можете просто отримати доступ до нього за допомогою програми « Спільний доступ до екрана (за замовчуванням)», підключившись до localhost:5901
.
Докерфайл:
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 для складання та запуску команд, якщо ви хочете / потребуєте.
Виходячи з відповіді Юргена Вайгерта , я вдосконалююсь:
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 переконайтеся, що зображення має таку ж реалізацію, як і хост.
Подібно до відповіді @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 і з мого контейнера для докерів Debian.
Докер з мережею 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
Ще одна відповідь у випадку, якщо ви вже створили зображення:
викликати docker без судо ( Як виправити докер: Отримано дозвіл відмовлено )
поділитися тим же USER & home & passwd між хостом та контейнером (поради: використовувати ідентифікатор користувача замість імені користувача)
папка dev для ліфтів, залежних від драйверів, для роботи
плюс 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} id -u ${USER}
--user = --env = "DISPLAY" --volume = "/ тощо / 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
Оновіть команду запуску докера
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
Докладніше: Використання графічного інтерфейсу з Docker
Кредит: виявлення об'єктів обміну в режимі реального часу та відео за допомогою Tensorflow, OpenCV та Docker