Как вы можете запускать приложения GUI в контейнере Docker?
Есть ли какие-либо изображения, которые устанавливают vncserver
или что-то такое, что вы можете - например - добавить дополнительную песочницу sandbox вокруг Firefox?
Как вы можете запускать приложения GUI в контейнере Docker?
Есть ли какие-либо изображения, которые устанавливают vncserver
или что-то такое, что вы можете - например - добавить дополнительную песочницу sandbox вокруг 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
:
Для Docker версии 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
Для Docker до версии 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
Xauthority становится проблемой с более новыми системами. Я могу либо отменить любую защиту с помощью xhost + перед запуском моих контейнеров докеров, либо я могу перейти в хорошо подготовленный файл Xauthority. Типичные файлы Xauthority - это имя хоста. С докере каждый контейнер может иметь другое имя хоста (установленное с помощью docker run -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
Я только что нашел эту запись в блоге и хочу поделиться ею с вами, потому что я считаю, что это лучший способ сделать это, и это так просто.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
ПЛЮСЫ:
+ нет сервера в контейнере докера
+ не нужен клиент/сервер vnc
+ no 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 .
и команда запуска:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
конечно, вы также можете сделать это в команде запуска с sh -c "echo script-here"
СОВЕТ: для аудио просмотра: fooobar.com/questions/27383/...
С тонами данных докеров очень легко выставить в контейнер контейнер xorg unix внутри контейнера.
Например, с помощью файла Docker, например:
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, которые были разработаны для решения вашей проблемы.
Вы также можете использовать subuser: https://github.com/timthelion/subuser
Это позволяет вам упаковывать многие приложения gui в докере. Firefox и emacs были протестированы до сих пор. С firefox webGL не работает. Хром не работает вообще.
EDIT: звук работает!
EDIT2: За время, прошедшее с момента первого опубликования этого сообщения, субаус значительно продвинулся. Теперь у меня есть веб-сайт subuser.org и новая модель безопасности для подключения к X11 через мост XPRA.
Юрген Вейгерт имеет лучший ответ, который работал на меня на Ubuntu, однако на OSX докер работает внутри VirtualBox, и поэтому решение не работает без каких-либо дополнительных работа.
У меня есть работа с этими дополнительными ингредиентами:
Я бы оценил комментарии пользователей, чтобы улучшить этот ответ для OSX, я не уверен, что пересылка сокетов для X является безопасной, но мое предназначение - использовать только локальный контейнер докера.
Кроме того, script является немного хрупким, так как он не просто получить IP-адрес машины, поскольку он находится на нашей локальной беспроводной сети, поэтому он всегда имеет случайный IP-адрес.
BASH script Я использую для запуска контейнера:
#!/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
Здесь приведено легкое решение, которое позволяет избежать установки любого сервера X
server, vnc
server или sshd
в контейнере. То, что он получает в простоте, теряет в безопасности и изоляции.
Предполагается, что вы подключаетесь к главной машине с помощью ssh
с пересылкой X11
.
В конфигурации sshd
хоста добавьте строку
X11UseLocalhost no
Чтобы переадресованный порт X-сервера на хосте был открыт на всех интерфейсах (а не только lo
) и, в частности, на виртуальном интерфейсе Docker, 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
Совместное использование дисплея хоста: 0, как указано в некоторых других ответах, имеет два недостатка:
xev
xinput
с помощью xev
или xinput
и удаленное управление хост-приложениями с помощью xdotool
.--ipc=host
изоляцию --ipc=host
).Ниже приведен пример сценария для запуска образа докера в Xephyr, который решает эту проблему.
--cap-drop ALL --security-opt no-new-privileges
. Также пользователь контейнера не является пользователем root.Скрипт ожидает некоторых аргументов: сначала менеджер окон хоста будет запущен в Xephyr, второй образ докера, опционально третья команда образа, которая будет выполнена. Чтобы запустить среду рабочего стола в Docker, используйте ":" вместо менеджера окон хоста.
Закрытие окна Xephyr завершает работу приложений Docker-контейнера. Завершение закрепленных приложений закрывает окно 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 wiki. Более сложный скрипт - x11docker, который также поддерживает такие функции, как ускорение графического процессора, совместное использование веб-камеры и принтера и так далее.
Это не легкий вес, но это приятное решение, обеспечивающее четность контроля докеров с полной виртуализацией рабочего стола. Оба Xfce4 или IceWM для Ubuntu и CentOS работают, а опция noVNC
обеспечивает легкий доступ через браузер.
https://github.com/ConSol/docker-headless-vnc-container
Он запускает noVNC
а также tigerVNC
vncserver. Затем он вызывает startx
для данного Window Manager. Кроме того, libnss_wrapper.so
используется для эмуляции управления паролями для пользователей.
Решение, данное на 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/
Хотя ответ Юргена Вайгерта, по сути, охватывает это решение, мне сначала было не ясно, что там описывалось. Поэтому я добавлю свою точку зрения на случай, если кому-то еще понадобятся разъяснения.
Прежде всего, соответствующей документацией является X-страница безопасности.
Многочисленные онлайн-источники предлагают просто смонтировать сокет X11 unix и файл ~/.Xauthority
в контейнер. Эти решения часто работают по счастливой случайности, не понимая, почему, например, пользователь контейнера получает тот же UID, что и пользователь, поэтому нет необходимости в авторизации с помощью магического ключа.
Прежде всего, файл Xauthority имеет режим 0600, поэтому пользователь контейнера не сможет его прочитать, если у него не будет того же UID.
Даже если вы копируете файл в контейнер и меняете владельца, возникает еще одна проблема. Если вы запустите xauth list
на хосте и в контейнере с одним и тем же файлом Xauthority
, вы увидите разные записи в списке. Это потому, что xauth
фильтрует записи в зависимости от того, где он работает.
X-клиент в контейнере (т.е. приложение с графическим интерфейсом) будет вести себя так же, как xauth
. Другими словами, он не видит волшебный cookie для сеанса X, запущенного на рабочем столе пользователя. Вместо этого он видит записи для всех "удаленных" сеансов X, которые вы открывали ранее (объяснено ниже).
Итак, вам нужно добавить новую запись с именем хоста контейнера и тем же шестнадцатеричным ключом, что и файл cookie хоста (т.е. Сеанс X, запущенный на вашем рабочем столе), например:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
xauth add
в том, что cookie должен быть добавлен с помощью xauth add
внутри контейнера:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
В противном случае, xauth
его так, чтобы он xauth
видеть только вне контейнера.
Формат этой команды:
xauth add hostname/$DISPLAY protocol hexkey
Где .
представляет протокол MIT-MAGIC-COOKIE-1
.
Примечание. Нет необходимости копировать или связывать. .Xauthority
в контейнер. Просто создайте пустой файл, как показано, и добавьте cookie.
Jürgen Weigert ответ обходит это, используя тип соединения FamilyWild
чтобы создать новый файл полномочий на хосте и скопировать его в контейнер. Обратите внимание, что сначала он извлекает шестнадцатеричный ключ для текущего сеанса X из ~/.Xauthority
используя xauth nlist
.
Итак, основные шаги:
FamilyWild
). Я признаю, что я не очень хорошо понимаю, как FamilyWild
работает, или как xauth
или записи X клиентов фильтра из файла Xauthority в зависимости, где они выполняются. Дополнительная информация об этом приветствуется.
Если вы хотите распространять свое приложение Docker, вам понадобится стартовый скрипт для запуска контейнера, который получает шестнадцатеричный ключ для сеанса пользователя X и импортирует его в контейнер одним из двух способов, описанных ранее.
Это также помогает понять механику процесса авторизации:
$DISPLAY
./tmp/.X11-unix
смонтированном в контейнере.Примечание. Сокет Unix X11 по-прежнему необходимо монтировать в контейнере, иначе у контейнера не будет маршрута к X-серверу. Большинство дистрибутивов по умолчанию отключают TCP-доступ к X-серверу.
Для получения дополнительной информации и лучшего понимания того, как работают отношения X клиент/сервер, полезно также рассмотреть пример пересылки SSH X:
$DISPLAY
в сеансе SSH для указания на свой собственный X-сервер.xauth
для создания нового файла cookie для удаленного хоста и добавляет его в файлы Xauthority
как для локальных, так и для удаленных пользователей.Если вы хотите запустить приложение GUI без заголовка, прочитайте здесь. Что вам нужно сделать, так это создать виртуальный монитор с помощью xvfb
или другого подобного программного обеспечения. Это очень полезно, если вы хотите запускать тесты Selenium, например, с браузерами.
Что-то не упоминалось нигде, так это то, что какое-то программное обеспечение фактически использует песочные боксы с контейнерами Linux. Так, например, Chrome никогда не будет работать нормально, если вы не используете соответствующий флаг --privileged
при запуске контейнера.
Существует другое решение от lord.garbage для запуска приложений GUI в контейнере без использования переадресации VNC, SSH и X11. Здесь упоминается здесь.
Я опаздываю на вечеринку, но для пользователей Mac, которые не хотят идти по пути XQuartz, вот рабочий пример, который создает образ Fedora с помощью среды рабочего стола (xfce) с использованием Xvfb
и VNC
. Это просто, и работает:
На Mac вы можете просто получить к нему доступ, используя приложение Screen Sharing (по умолчанию), подключившись к 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 для команд build и run, если хотите/нуждаетесь.
На основе Юрген Вейгерт ответ, у меня есть некоторые улучшения:
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
Afterall, контейнер будет автоматически получать файл Xauthority каждый раз при перезапуске системы и входе пользователя в систему.
Для рендеринга OpenGL с драйвером Nvidia используйте следующее изображение:
https://github.com/thewtex/docker-opengl-nvidia
Для других реализаций OpenGL убедитесь, что изображение имеет ту же реализацию, что и хост.
Другие решения должны работать, но вот решение для docker-compose
.
Чтобы исправить эту ошибку, вам нужно передать $ DISPLAY и .X11-unix в Docker, а также предоставить пользователю, запустившему Docker, доступ к 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
Вы можете разрешить пользователю Docker (здесь: root) получить доступ к экрану X11:
XSOCK=/tmp/.X11-unix
xhost +SI:localuser:root
docker run -t -i --rm -v $XSOCK:$XSOCK:ro -e DISPLAY=unix$(DISPLAY) image
xhost -SI:localuser:root
Подобно @Nick ответ, но его решение не сработало для меня.
Сначала установите socat, выполнив brew install socat
и установите XQuartz (https://www.xquartz.org/)
Затем выполните следующие шаги (http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/) в разделе комментариев:
1. in one mac terminal i started:
socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"
2. and in another mac terminal I ran:
docker run -ti --rm \
-e DISPLAY=$(ipconfig getifaddr en0):0 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
Я также смог запустить CLion из моего контейнера дойкеров debian.
Докер с сетью МОСТ. для 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 без sudo (Как исправить docker: проблема с запрещенным доступом)
использовать один и тот же пользователь USER & home & passwd для общего ресурса хоста и контейнера (советы: используйте имя пользователя вместо имени пользователя)
папка dev для зависимых от драйвера библиотек для правильной работы
плюс Х11 вперед.
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
Вы можете спросить, какой смысл использовать Docker, если так много вещей одинаковы? ну, одна из причин, по которой я могу придумать, - это преодолеть ад зависимости пакетов (https://en.wikipedia.org/wiki/Dependency_hell).
Так что этот тип использования больше подходит для разработчика, я думаю.